bash-скрипт, собирающий имена файлов, кажется, запутан пробелами - PullRequest
1 голос
/ 29 февраля 2012

Я пытаюсь создать скрипт, который перечисляет все zip-файлы в наборе каталогов, с некоторыми фильтрами и заставляет его выкладывать их в файл, но когда в имени файла есть пробел, он, кажется, появляется на новая строка.

Этот список в конечном итоге будет использоваться в качестве входных данных для tar, чтобы сжать все zip-файлы, скрипт приведен ниже:

#!/bin/bash
rm -f set1.txt

rm -f set2.txt

for line in $(find /home -type d -name assets ;); 

do 

    echo $line >> set1.txt

    for line in $(find $line -type f -name \*.zip -mtime +2  ;);

    do

        echo \"$line\"  >> set2.txt     

    done; 

Это работает, как и ожидалось, пока вы не получите пробел в имени файла, тогда set2.txt содержит записи вроде этого:

"/home/xxxxxx/oldwebroot/htdocs/upload/assets/jobbags/rbjbCost"

"in"

"use"

"sept"

"2010.zip"

Кто-нибудь знает, как я могу заставить эти имена файлов с пробелами быть в одной строке с целым лотом, заключенным в один набор кавычек?

Спасибо!

Ответы [ 2 ]

4 голосов
/ 29 февраля 2012

Правильный способ зацикливания набора файлов, расположенных с помощью find, - это конструкция с чтением, поэтому:

while IFS= read -r  -d '' line ; do
    echo "$line" >> set1.txt
    while IFS= read -r -d '' file ; do
            printf '"%s"\n' "$file" >> set2.txt
    done < <(find "$line" -type f -name \*.zip -mtime +2 -print0)
done < <(find /home -type d -name assets -print0)

Для ясности я присвоил переменной внутреннего цикла другое имя.

Если у вас не было bash, вам нужно было бы отдельно ввести команду find и перенаправить вывод в файл, а затем прочитать файл с помощью while read ; do .. done < filename.

Примечание.что каждое расширение каждой переменной заключено в двойные кавычки.Это необходимо.

Обратите внимание, однако, что для того, что вы хотите, вы можете просто использовать переключатель -printf на find, если у вас есть GNU find.

find /home -type f -path '*/assets/*.zip' -mtime +2 -printf '"%p"\n' > set2.txt

Хотя, как отмечает @sarnold, это небезопасно.

1 голос
/ 29 февраля 2012

Вы, вероятно, должны выполнять команду tar(1) через какой-то другой механизм; программа find(1) поддерживает опцию -print0 для запроса вывода имени файла, разделенного ASCII NUL, а программа xargs(1) поддерживает опцию -0, чтобы сообщить ей, что ввод разделен символами ASCII NUL. (Поскольку NUL является единственным символом, который не разрешен в именах файлов, это единственный способ получить надежную обработку имени файла.)

Простое использование параметров -print0 и -0 поможет help , но это все еще оставляет сценарий открытым для другой проблемы - xargs(1) может решить выполнить команду tar(1) два, три, или более раз, в зависимости от его ввода. Последнее выполнение - это то, что «победит», и данные от предыдущих вызовов будут потеряны навсегда. (Это бесполезно в качестве резервной копии.)

Так что вам также следует добавить параметр командной строки --concatenate к tar(1), чтобы он добавил в архив. Возможно, имеет смысл выполнить сжатие после того, как все файлы были добавлены, через gzip(1) или bzip2(1). (Это означает, что вам нужно удалить архива перед «новым запуском» этого скрипта.)

...