Подтвердить что ты не робот

Как я могу прочитать список имен файлов из файла в bash?

Я пытаюсь написать bash script, который будет обрабатывать список файлов, имена которых хранятся по одному на строку во входном файле, что-то вроде

find . -type f -mtime +15 > /tmp/filelist.txt
for F in $(cat /tmp/filelist.txt) ; do
  ...
done;

Моя проблема в том, что имена файлов в файлеlistlist.txt могут содержать пробелы, поэтому вышеперечисленное будет расширять строку

my text file.txt

для трех разных имен файлов, my, text и file.txt. Как я могу это исправить?

4b9b3361

Ответ 1

Используйте read:

while read F  ; do
        echo $F
done </tmp/filelist.txt

В качестве альтернативы используйте IFS, чтобы изменить, как оболочка разделяет ваш список:

OLDIFS=$IFS
IFS="
"
for F in $(cat /tmp/filelist.txt) ; do
  echo $F
done
IFS=$OLDIFS

Альтернативно (как было предложено @tangens), преобразуйте тело вашего цикла в отдельный script, затем используйте find -exec вариант для запуска, если для каждого найденного файла напрямую.

Ответ 2

Вы можете сделать это без временного файла, используя замену процесса:

while read F
do
  ...
done < <(find . -type f -mtime +15)

Ответ 3

использовать при чтении

echo $FILE | while read line
do
echo $line
done

Вы можете перенаправлять вместо echo

Ответ 4

Вы можете использовать параметр -exec find и напрямую использовать имена файлов:

find . -type f -mtime +15 -exec <your command here> {} \;

{} является заполнитель для имени файла.

Ответ 5

нажимайте команду поиска прямо во время цикла чтения

find . -type f -mtime +15 | while read -r line
do
   printf "do something with $line\n"
done

Ответ 6

Я не эксперт bash любым способом (обычно я пишу свой script в ruby ​​или python как кросс-платформенный), но я бы использовал экспрессию регулярного выражения, чтобы избежать пробелов в каждой строке, прежде чем обрабатывать он.

Для bash Regex: http://www.linuxjournal.com/node/1006996

В аналогичной ситуации в Ruby (обработка файла csv и очистка каждой строки перед ее использованием):

File.foreach(csv_file_name) do |line| 
    clean_line = line.gsub(/( )/, '\ ') 
    #this finds the space in your file name and escapes it    
    #do more stuff here
end  

Ответ 7

Я считаю, что вы можете полностью пропустить временный файл и просто напрямую перебирать результаты поиска, т.е.:

for F in $(find . -type f -mtime +15) ; do
  ...
done;

Нет гарантий, что мой синтаксис верен, но я уверен, что концепция работает.

Изменить: если вам действительно нужно обработать файл со списком имен файлов и не можете просто комбинировать команды, как я сделал выше, то вы можете изменить значение переменной IFS - это означает, что внутри Полевой разделитель - изменить, как bash определяет поля. По умолчанию он имеет значение пробела, поэтому новая строка, пробел или вкладка начнут новое поле. Если вы установите для него только новую строку, вы можете перебирать файл так же, как и раньше.