Так, скажімо, у мене є каталог з купою файлів на зразок g.txt, де g.txt востаннє змінено, скажімо, 20 червня 2012 року.
Як я міг би перейменувати всі файли (наприклад, g.txt) з останньою зміненою датою 20 червня 2012 року, доданою в кінці?
Так, скажімо, у мене є каталог з купою файлів на зразок g.txt, де g.txt востаннє змінено, скажімо, 20 червня 2012 року.
Як я міг би перейменувати всі файли (наприклад, g.txt) з останньою зміненою датою 20 червня 2012 року, доданою в кінці?
Відповіді:
Швидкий і брудний Bash один вкладиш перейменувати всі файли (globbed) в поточному каталозі від filename.txt
до filename.txt-20120620
:
for f in *; do mv -- "$f" "$f-$(stat -c %Y "$f" | date +%Y%m%d)"; done
Заповзятливий ботанік Баша знайде певний край, щоб його зламати, я впевнений. :)
Очевидно, що це не робить бажаних речей, таких як перевірка того, чи у файлі вже є щось, схоже на дату в кінці.
date
реалізація? Моя GNU date
, здається, не обробляє введення.
Ось версія однолінійки Goldschrafe, що:
також справляється з назви файлів, починаючи з тире
for f in *; do mv -- "$f" "$f-$(date -r "$f" +%Y%m%d)"; done
date -r "$f" +%Y%m%d
або він не спрацює, якщо POSIXLY_CORRECT
знаходиться в навколишньому середовищі. Як правило, варіанти повинні йти перед іншими аргументами.
"${f}"
.
Обов'язковий однолінійний zsh (не рахуючи одноразового завантаження додаткових компонентів):
zmodload zsh/stat
autoload -U zmv
zmv -n '(*)' '$1-$(stat -F %Y%m%d +mtime -- $1)'
Ми використовуємо stat
вбудований zsh/stat
модуль і zmv
функцію для перейменування файлів. І ось додатковий, який розміщує дату перед розширенням, якщо така є.
zmv -n '(*)' '$1:r-$(stat -F %Y%m%d +mtime -- $1)${${1:e}:+.$1:e}'
Як я зрозумів, ми заздалегідь не знаємо, яка дата зміни. Тому нам потрібно отримати його з кожного файлу, відформатувати вихід і перейменувати кожен файл таким чином, щоб він включав дату модифікації у назви файлів.
Ви можете зберегти цей скрипт як щось на зразок "modif_date.sh" і зробити його виконуваним. Ми викликаємо його з цільовим каталогом як аргумент:
modif_date.sh txt_collection
Де "txt_collection" - це ім'я каталогу, де у нас є всі файли, які ми хочемо перейменувати.
#!/bin/sh
# Override any locale setting to get known month names
export LC_ALL=c
# First we check for the argument
if [ -z "$1" ]; then
echo "Usage: $0 directory"
exit 1
fi
# Here we check if the argument is an absolute or relative path. It works both ways
case "${1}" in
/*) work_dir=${1};;
*) work_dir=${PWD}/${1};;
esac
# We need a for loop to treat file by file inside our target directory
for i in *; do
# If the modification date is in the same year, "ls -l" shows us the timestamp.
# So in this case we use our current year.
test_year=`ls -Ggl "${work_dir}/${i}" | awk '{ print $6 }'`
case ${test_year} in *:*)
modif_year=`date '+%Y'`
;;
*)
modif_year=${test_year}
;;
esac
# The month output from "ls -l" is in short names. We convert it to numbers.
name_month=`ls -Ggl "${work_dir}/${i}" | awk '{ print $4 }'`
case ${name_month} in
Jan) num_month=01 ;;
Feb) num_month=02 ;;
Mar) num_month=03 ;;
Apr) num_month=04 ;;
May) num_month=05 ;;
Jun) num_month=06 ;;
Jul) num_month=07 ;;
Aug) num_month=08 ;;
Sep) num_month=09 ;;
Oct) num_month=10 ;;
Nov) num_month=11 ;;
Dec) num_month=12 ;;
*) echo "ERROR!"; exit 1 ;;
esac
# Here is the date we will use for each file
modif_date=`ls -Ggl "${work_dir}/${i}" | awk '{ print $5 }'`${num_month}${modif_year}
# And finally, here we actually rename each file to include
# the last modification date as part of the filename.
mv "${work_dir}/${i}" "${work_dir}/${i}-${modif_date}"
done
stat
корисність або взагалі жодну.
ls
не є надійним . У деяких варіантах unix імена користувачів та груп можуть містити пробіли, які скидають вирівнювання стовпців дати.
ls
як дата та час (а не дата та рік), повинні бути у поточному році. Це не правда. Це за останні півроку; що може бути в попередньому році (наприклад, з 27 вересня по 31 грудня 2016 року є протягом останніх шести місяців). (6) Загрожуючи папугою Вікі Грега (який @Gilles вже цитував), назви файлів, які містять нові рядки та пробіли, можуть призвести до цього невдачі. … (Продовження)
Ось версія Oneliner КАН ( на основі Oneliner goldschrafe в) розширено ідемпотентності ,
тобто поширюється на префіксні файли з датою і робити це лише для тих, хто ще не має префікса часу .
Use-case: корисно, якщо ви додаєте нові файли в каталог і хочете додати префікс часу дати до тих, у яких ще немає.
for f in * ; do
if [[ "$f" != ????-??-??' '??:??:??' - '* ]]; then
mv -v -- "$f" "$(date -r "$f" +%Y-%m-%d' '%H:%M:%S) - $f" ;
fi;
done
for f in *.jpg ; do jhead -ft "$f" ; done
джерело: unix.stackexchange.com/a/290755/9689