проблема в том, что обратные кавычки в строке
if [ -f `sources/*.bak` ]
`
имеют особое значение в bash: они используются для оценки команды и возврата ее вывода.
Например. Если ваше имя пользователя frodl , то
if [ -f `whoami` ]
проверит, существует ли файл с именем frodl
.
Итак, если вы напишете sources / *. Bak
, он сначала попытается подобрать термин sources / *. Bak
, но поскольку в нет файлов sources /
с расширением .bak
, термин не будет расширен. Затем он попытается запустить буквальный термин sources / *. Bak
, который не является допустимой командой (на самом деле вы можете иметь файл с именем sources / *. Bak
] (имя файла со звездочкой в начале; содрогнитесь!), но похоже, что это не так. Однако этот файл будет иметь расширение .bak
, что мы исключали ранее.)
Если у вас есть файл sources / deletemyharddisk.bak
, то термин sources / * .bak
будет расширен до этой строки, а затем попытается выполнить его (потенциально удаляя ваш жесткий диск ).
Итак, что вам нужно сделать, это использовать обычные кавычки.
backupfiles=sources/*.bak
if [ "x${backupfiles}" = "xsources/*.bak" ]; then
echo "no .bak files" 1>&2
else
echo "there are .bak files"...
fi
Сначала будет предпринята попытка расширить термин sources / * .bak
в переменную backupfiles
. Если есть какие-либо bak-файлы, это станет строкой всех имен файлов; если их нет, это останется нерасширенной строкой.
Если вы затем сравните результат с буквальным (нерасширенным) sources / *.bak
вы можете сказать, имело ли место расширение (из-за наличия совпадающих файлов) или нет.
, однако, нет особых причин сначала проверять, есть ли файлы, а затем удалять их.
Более простой подход - просто удалить все файлы, соответствующие заданному шаблону. {{ 1}} find
может сделать это за вас:
find sources/ -maxdepth 1 -type f -name "*.bak" -delete
(будет выполняться поиск файлов на первом уровне ( -maxdepth 1
) каталога sources /
( -type f
; а не каталоги, символические ссылки или другие вещи), которые заканчиваются на .bak
( -name "* .bak"
), а затем удалите их ( -delete
)
ls
Другая проблема с вашим кодом -
target_files=`echo -n $(ls sources/{*.c,*.h})`
for i in $target_files
...
Вы не должны никогда анализировать вывод ls
.
Вместо этого используйте что-то вроде
for i in sources/*.c sources/*h
do
#...
done
Команда:
ls | grep mp4 | xargs -i mv {} mp4
в большинстве случаев может быть заменена более простой и надежной:
mv *mp4* mp4
Вы можете игнорировать предупреждение о том, что каталог mp4 не может перемещаться внутри себя.
Обратите внимание, что этот скрипт, как и ваш, перемещает все файлы, в имени которых есть « mp4
» (например: mp4list.txt
, lamp4.jpg
). Если вы действительно хотите переместить только файлы с расширением « .mp4
», вы можете использовать:
mv *.mp4 mp4
Это предотвратит ситуацию, приводящую к появлению сообщения об ошибке самого каталога mp4
происходить.
Если количество файлов mp4 слишком велико и первая команда не работает, вы можете использовать GNU find
, чтобы добиться того же:
find . -maxdepth 1 -name "*mp4*" -exec mv -t mp4 {} +
или
find . -maxdepth 1 -name "*.mp4" -exec mv -t mp4 {} +
Это как раз та ситуация , в которой вы не хотите использовать ls
. Или xargs
с настройками по умолчанию, он разбивает ввод по пробелам и специально обрабатывает кавычки и обратную косую черту.Вам нужно будет использовать -0
для разделения ввода по нулевым байтам или -d '\ n'
для разделения по новой строке (GNU xargs), чтобы отключить это поведение.
Поскольку все файлы находятся в одном каталоге, вы можете просто использовать оболочку:
mv *mp4* mp4/
Или mv * .mp4 mp4 /
, если вы имели в виду только файлы, содержащие mp4
как расширение. Первый предупреждает о перемещении самого mp4
в mp4
.)
Если бы файлы не находились в том же каталоге, вам нужно было бы использовать двойную звездочку ( zsh
- включен по умолчанию или ksh
с помощью установить -o globstar
или bash
с shopt -s globstar
) :
mv **/*mp4* mp4/
или найти
find . -type f -name "*mp*" -exec mv {} mp4/ \;