У меня есть bash-скрипт, который переименовывает файлы в папке в соответствии с вводом из командной строки:
echo "Please rename and press enter" read rename
if [ -z "$rename" ]; then
printf "no caption was selected, aborting!\n"
exit 1
fi
printf "rename is $rename\n" count=1
for i in *.jpg; do
j=printf "%04d" $count
j="$rename"$j".jpg"
count=$((count + 1))
mv "$i" $j
done
fi
shift
done
Как изменить этот скрипт, чтобы файлы в папке переименовывались в соответствии с их размером?
Если отсортировать файлы по размеру, то в папке они будут выглядеть так:
a009 978kb
a001 567kb
a003 499kb
a008 432kb
Поэтому я хочу переименовать полученные файлы:
a001 978kb
a002 567kb
a003 499kb
a004 432kb
решение1
Что-то вроде этого:
echo "Please rename and press enter"
read rename
ls |
# prepend filename with file size in bytes
parallel stat -c %s,,sep,,%n -- |
# sort by number
sort -n |
# rename to sequencenumber followed by size in bytes
parallel -q --colsep ,,sep,, mv {2} "$rename"{#}_{1}
решение2
Главный трюк — заменить
for i in *.jpg
с
for i in $(ls -S *.jpg)
Однако, как указал Кусалананда, это предполагает «образованные» имена файлов (без пробелов и управляющих символов), поэтому вот другой подход:
count=1
ls -S --escape *.jpg | while read f; do
n=$(printf "%04d" $count)
((count++))
mv --no-clobber "$f" "$rename$n.jpg"
done
-S
сортировка по уменьшению размера файла
--escape
предотвращает повреждение имен со встроенными переносами строк
--no-clobber
предотвращает перезапись целевых файлов в случае, если скрипт запускается дважды
P.S. Ответ Оле Танге — очень хороший и эффективный способ сделать то же самое, но вы, вероятно, не увидите разницы, если только не будете регулярно переименовывать тысячи файлов.
решение3
В zsh
оболочке:
typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
count=$(( count + 1 ))
mv -i -- "$name" "a$count.jpg"
done
Это переберет все обычные файлы с .jpg
суффиксом имени файла в текущем каталоге в порядке от наибольшего к наименьшему. Для каждого файла он переименует его в , aNNN.jpg
где NNN
— заполненное нулями целое число файлов, обработанных до сих пор.
Квалификатор (.DNOL)
glob упорядочивает соответствующие имена файлов в правильном порядке с помощью OL
("reverse order by length") и выбирает только обычные файлы (включая скрытые имена) с помощью .D
("regular files, and dot-files"). Это N
заставляет шаблон расширяться до нуля, если нет соответствующего имени ("null glob").
Это будет работать со всеми допустимыми именами файлов в любой zsh
установленной системе Unix.
Чтобы использовать это из bash
:
zsh -c 'typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
count=$(( count + 1 ))
mv -i -- "$name" "a$count.jpg"
done'
Если у вас есть переменная $rename
, которую вы хотите передать как префикс имени файла вместо использования a
:
zsh -c 'typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
count=$(( count + 1 ))
mv -i -- "$name" "$1$count.jpg"
done' zsh "$rename"
Обратите внимание, что zsh
в последней строке не является опечаткой и что значение $rename
используется $1
внутри zsh -c
скрипта.