Каков наилучший способ, используя Bash, переименовать файлы в форме:
(foo1, foo2, ..., foo1300, ..., fooN)
С нумерованными именами файлов:
(foo00001, foo00002, ..., foo01300, ..., fooN)
Каков наилучший способ, используя Bash, переименовать файлы в форме:
(foo1, foo2, ..., foo1300, ..., fooN)
С нумерованными именами файлов:
(foo00001, foo00002, ..., foo01300, ..., fooN)
В случае, если N
не является априорным:
for f in foo[0-9]*; do mv $f `printf foo%05d ${f#foo}`; done
Это не чисто bash, но гораздо проще с командой rename
:
rename 's/\d+/sprintf("%05d",$&)/e' foo*
У меня был более сложный случай, когда имена файлов имели постфикс, а также префикс. Мне также нужно было выполнить вычитание числа из имени файла.
Например, я хотел, чтобы foo56.png
стал foo00000055.png
.
Надеюсь, это поможет, если вы делаете что-то более сложное.
#!/bin/bash
prefix="foo"
postfix=".png"
targetDir="../newframes"
paddingLength=8
for file in ${prefix}[0-9]*${postfix}; do
# strip the prefix off the file name
postfile=${file#$prefix}
# strip the postfix off the file name
number=${postfile%$postfix}
# subtract 1 from the resulting number
i=$((number-1))
# copy to a new name with padded zeros in a new folder
cp ${file} "$targetDir"/$(printf $prefix%0${paddingLength}d$postfix $i)
done
Команда oneline, которую я использую, такова:
ls * | cat -n | while read i f; do mv "$f" `printf "PATTERN" "$i"`; done
PATTERN может быть, например:
%04d.${f#*.}
(сохранить исходное расширение файла)photo_%04d.${f#*.}
(сохранить исходное расширение)%04d.jpg
photo_$(basename $f .${f#*.})_%04d.${f#*.}
Вы можете отфильтровать файл для переименования, например, ls *.jpg | ...
У вас есть переменная f
, которая является именем файла и i
, которая является счетчиком.
По вашему вопросу правильная команда:
ls * | cat -n | while read i f; do mv "$f" `printf "foo%d05" "$i"`; done
Pure Bash, никаких внешних процессов, кроме "mv":
for file in foo*; do
newnumber='00000'${file#foo} # get number, pack with zeros
newnumber=${newnumber:(-5)} # the last five characters
mv $file foo$newnumber # rename
done
Следующие будут делать это:
for ((i=1; i<=N; i++)) ; do mv foo$i 'printf foo%05d $i' ; done
РЕДАКТИРОВАТЬ: изменено для использования ((i = 1,...)), спасибо mweerden !
Здесь быстрое решение, которое предполагает префикс фиксированной длины (ваш "foo" ) и заполнение фиксированной длины. Если вам нужна большая гибкость, возможно, это будет, по крайней мере, полезной отправной точкой.
#!/bin/bash
# some test data
files="foo1
foo2
foo100
foo200
foo9999"
for f in $files; do
prefix=`echo "$f" | cut -c 1-3` # chars 1-3 = "foo"
number=`echo "$f" | cut -c 4-` # chars 4-end = the number
printf "%s%04d\n" "$prefix" "$number"
done
Мое решение заменяет числа, везде в строке
for f in * ; do
number='echo $f | sed 's/[^0-9]*//g''
padded='printf "%04d" $number'
echo $f | sed "s/${number}/${padded}/";
done
Вы можете легко попробовать его, так как он просто печатает преобразованные имена файлов (операции с файловой системой не выполняются).
Цикл: for f in *; do ;done
for f in *; do ;done
, перечисляет все файлы и передает каждое имя файла как переменную $f
в тело цикла.
С echo $f | sed
echo $f | sed
мы передаем переменную $f
в программу sed
.
В команде sed 's/[^0-9]*//g'
, часть [^0-9]*
с модификатором ^
указывает на совпадение с цифрой 0-9 (не числом), а затем удаляет его с пустым замена //
. Почему бы просто не удалить [az]
? Поскольку имя файла может содержать точки, тире и т.д. Итак, мы удаляем все, что не является числом, и получаем число.
Далее мы присваиваем результат number
переменной. Не забудьте не ставить пробелы в присваивании, например, number = …
, потому что у вас другое поведение.
Мы присваиваем результат выполнения команды переменной, заключая команду в символы backtick '.
Команда printf "%04d" $number
меняет формат числа на 4 цифры и добавляет нули, если наш номер содержит менее 4 цифр.
Мы снова используем sed
с командой замены, например, s/substring/replacement/
. Чтобы интерпретировать наши переменные, мы используем двойные кавычки и подставляем наши переменные таким образом: ${number}
.
Приведенный выше скрипт просто печатает преобразованные имена, поэтому давайте сделаем реальную работу по переименованию:
for f in *.js ; do
number='echo $f | sed 's/[^0-9]*//g''
padded='printf "%04d" $number'
new_name='echo $f | sed "s/${number}/${padded}/"'
mv $f $new_name;
done
Надеюсь, это кому-нибудь поможет.
Я потратил несколько часов, чтобы понять это.
Чтобы номера левой панели в именах файлов:
$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 1.zzz
$ for f in [0-9]*.[a-z]*; do tmp='echo $f | awk -F. '{printf "%04d.%s\n", $1, $2}''; mv "$f" "$tmp"; done;
$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0001.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
объяснение
for f in [0-9]*.[a-z]*; do tmp='echo $f | \
awk -F. '{printf "%04d.%s\n", $1, $2}''; mv "$f" "$tmp"; done;
'echo... $2}\'
(обратная косая черта, \, сразу же над ней, просто разделяет эту строку на две строки для удобства чтения)[0-9]*.[az]*
$f
), чтобы передать его в awk
-F.
: разделитель полей awk
, точка (.
): при совпадении разделяет имена файлов на два поля ($1
= число; $2
= расширение)printf
: напечатайте первое поле ($1
, %04d
часть) как 4 цифры (%04d
), затем напечатайте точку, затем напечатайте второе поле ($2
: расширение) в виде строки (%s
). Все это присваивается переменной $tmp
$f
) на новое имя файла ($tmp
)