Как переместить файлы с именем, содержащим несколько специальных символов, например 'é' 'ä' 'space'?

проблема в том, что обратные кавычки в строке

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

1
15.04.2017, 02:30
2 ответа

Команда:

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 {} +
4
27.01.2020, 23:12

Это как раз та ситуация , в которой вы не хотите использовать 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/ \;
5
27.01.2020, 23:12

Теги

Похожие вопросы