Я хочу узнать больше, поэтому я пытался писать больше, чем просто используя терминал. Я знаю rename
, и я могу переименовать файлы изображений с помощью rename 's/ /_/g' *.jpg
, но когда я пишу его в сценарии оболочки, чтобы указать на каталог:
DIRECTORY="/foo/bar"
for imgfile in $(find $DIRECTORY -type f -name \*.jpg); do
echo 'replacing whitespace in' $(basename $imgfile)
rename -f 's/ /_/g' *.jpg
done
он не работает, и терминал примет файл (пример: 1234 abcd.jpg
) и эхо abcd.jpg
. Так, где я иду не так?
Пробелы в именах файлов являются злыми.
Я вижу три проблемы со сценарием:
при выполнении for...
цикл, у Вас будет два различных значения при нахождении файла с пространством. т.е. если у Вас есть файлы "file1 1.jpg"
и "file2 2.jpg"
и Вы делаете:
for i in $(find . -type f -name \*.jpg); do
echo $i
done
Вы будете иметь
./file1
1.jpg
./file2
2.jpg
потому что оболочка повреждает аргумент в пробелах. Вывод $(find ...)
команда будет
./file1 1.jpg
./file2 2.jpg
Которые являются четырьмя словами для команды for
быть присвоенным в $i
---по умолчанию оболочка рассматривает пробелы и новые строки таким же образом при расширении.
Можно обойти это изменение символа IFS.
Ваша первая строка могла быть похожей:
IFS=$'\n' find $DIRECTORY -type f -name \*.jpg | while read -r imgfile; do
Вы питаетесь для цикла с единственным именем файла, таким образом, необходимо сказать:
rename -f 's/ /_/g' "$imgfile"
иначе *.jpg
расширен в текущем каталоге, а не в $DIRECTORY
(и отметьте кавычки---, учитывая, что $imgfile
движение должно иметь пробелы в нем).
даже затем, если $DIRECTORY
имеет некоторый компонент контура с пробелами в нем, переименовывание перестанет работать (будут промежуточные каталоги, которые не существуют).
предложение (сохраняющий это простой):
DIRECTORY="/foo/bar"
cd $DIRECTORY
rename -f 's/ /_/g' *.jpg
не делает то, что Вы хотите?
Добавленный: мой сценарий (созданный давным-давно, когда было нет rename
в Unix), этот---, он удалит пробелы и вкладку во всех файлах в текущем dir, которые имеют их на имя:
#
ls -1 | grep -E " |\t" | while read i; do
a=`echo $i | tr " \t" "__"`
mv -v "$i" $a
done
Добавленный ++: эта ссылка я нашел исследование этого ответа, превосходна.
Лучший способ проанализировать результат find
пустым указателем, оконечным вывод с -print0
#!/bin/bash
while IFS= read -d '' -r; do
rename -f "s/ /_/g" "$REPLY"
if [[ ! -f $REPLY ]]; then
echo "Renaming file: $(basename "$REPLY")"
fi
done < <(find -type f -name '*.jpg' -print0)
(Можно справиться без цикла).
$ find -type f -name '*.jpg' \
-exec bash -c 'rename -f "s/ /_/g" "$1"; \
[[ -f $1 ]] || echo "Renaming file: $(basename "$1")"' _ '{}' \;