Имена файлов с пробелами в BASH
Я пытаюсь написать script, который обрезает и изменяет размер больших фотографий в HD Wallpapers.
#! /bin/bash
for i in `ls *.jpg`
do
width=`identify -format '%w' $i`
height=`identify -format '%h' $i`
if [ `echo "$width/$height > 16/9" | bc -l` ]
then
exec `convert $i -resize 1920 -gravity Center -crop '1920x1080+0+0' +repage temp`
else
exec `convert $i -resize x1080 -gravity Center -crop 1920x1080+0+0 +repage temp`
fi
rm $i
mv temp $i
done
Но похоже, что script имеет проблемы с именами файлов, имеющими пробелы (например, Tumble Weed.jpg). Как я могу это исправить?
Ответы
Ответ 1
Во-первых, вам не нужно ls
. Используя ls
в backtics, вы неявно сделаете bash разбор строки в список, который разбивается на пробелы. Вместо этого сделайте bash сгенерируйте список и разделите его без таких причуд:
Кроме того, вам нужно заключить все $i
в кавычки, чтобы сделать bash заменить его как целое, а не как разделение строки для разделения слов.
Здесь script, который демонстрирует обе идеи:
for i in *.jpg ; do
echo "$i";
done
Ответ 2
Используйте чтение, чтобы обойти проблему с пробелами. Для написания цикла это выглядит немного неестественно, но он работает лучше:
find . -type f -iname "*.jpg" | while read i
do
# your original code inside the loop using "$i" instead of $i
done
с -iname
вы также получите файлы jpg, которые могут иметь расширение с другим корпусом, например .JPG. "i" в "iname" означает игнорировать корпус.
Ответ 3
Я бы рекомендовал написать строку для строки следующим образом:
for i in *.jpg
и инкапсулируйте $i
в двойные кавычки: "$i"
.
Если вы настаиваете на
`ls *.jpg`
style (если вы, например, получите свои имена файлов из более сложной команды), вы можете попробовать установить IFS
на \n
:
IFS='\n'
Сравните эти два исполнения:
$ for f in `ls *`; do echo $f; done
hello
world
test
$ IFS='\n'; for f in `ls *`; do echo $f; done
hello world
test
Ответ 4
В bash используйте замену строки с помощью find
${строка//подстрока/замена}
Replace all matches of $substring with $replacement.
так что это работает:
найти. -type f -name '*.jpg' | при чтении i; do/bin/mv -f "$ i" ${i///_}; сделано
Ответ 5
Используйте двойные кавычки вокруг имен файлов. Вот так:
width=`identify -format '%w' "$i"`
Обратите внимание на двойные кавычки вокруг "$i"
.
Ответ 6
#! /bin/bash
mkfifo ./lsOutput
ls -1 *.jpg > ./lsOutput
while read line
do
width=`identify -format '%w' "$line"`
height=`identify -format '%h' "$line"`
if [ `echo "$width/$height > 16/9" | bc -l` ]
then
exec `convert "$line" -resize 1920 -gravity Center -crop '1920x1080+0+0' +repage temp`
else
exec `convert "$line" -resize x1080 -gravity Center -crop 1920x1080+0+0 +repage temp`
fi
rm "$line"
mv temp "$line"
done<./lsOutput