Как скопировать содержимое каждого файла в списке в другой файл?

15

У меня есть список имен файлов внутри файла с именем list_of_files.txt.

Я хочу скопировать содержимое каждого файла в этом списке в другой файл с именем all_compounds.sdf .

Как я должен сделать это из командной строки?

Рамита Раджаа
источник

Ответы:

20

Не используйте простую подстановку команд для получения имен файлов (которые могут легко разрываться с пробелами и другими специальными символами). Используйте что-то вроде xargs:

xargs -d '\n' -a list_of_files.txt cat > all_compounds.sdf

Или while readцикл:

while IFS= read -r file; do cat "$file"; done < list_of_files.txt > all_compounds.sdf

Чтобы безопасно использовать подстановку команд, по крайней мере, установите IFSтолько новую строку и отключите глобализацию (расширение по шаблону):

(set -f; IFS=$'\n'; cat $(cat list_of_files.txt) > all_compounds.sdf)

Круглые скобки ()должны запускать это в подоболочке, чтобы эти изменения не повлияли на вашу текущую оболочку.

Мур
источник
14

Быстрый и грязный способ ...

cat $(cat list_of_files.txt) >> all_compounds.sdf

Обратите внимание: это работает только в том случае, если имена файлов в вашем списке очень хорошо себя ведут - все пойдет не так, если они содержат пробелы, символы новой строки или любые символы, которые имеют особое значение для оболочки - используйте вместо этого ответ для получения надежных результатов)

Примечания

  • catcon cat создает файлы. Он также печатает их содержимое.
  • Используя подстановку команд, command2 $(command1)вы можете передать вывод command1( cat list...) в command2( cat), который объединяет файлы.
  • Затем используйте перенаправление >>для отправки вывода в файл вместо печати на стандартный вывод. Если вы хотите увидеть вывод, используйте teeвместо этого:

    cat $(cat list_of_files.txt) | tee -a all_compounds.sdf

(Я использовал >>вместо >и teeс -aпереключателем, если ваш файл уже существует - он добавляется к файлу, а не перезаписывает его, если он уже существует)

Занна
источник
1
@Zanna цитирует подстановки команд, чтобы избежать разбиения слов, например"$(cat list_of_files.txt)"
Сергей Колодяжный
4
@Serg, если разбиение слов не выполнено, тогда catвесь список получает как один аргумент.
Муру
@muru Хорошо, тогда как нам обращаться с именами файлов, которые содержат пробелы?
Сергей Колодяжный
1
@Serg установите IFS соответствующим образом - см. Последний абзац моего ответа
Muru
4

Хотя GNU awk- это утилита обработки текста, она позволяет запускать команды внешней оболочки через system()вызов. Мы можем использовать это в наших интересах следующим образом:

$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt                                                        

Идея здесь проста: мы читаем файл построчно, и из каждой строки мы создаем отформатированную строку cat "File name.txt", которая затем передается system().

И вот оно в действии:

$ ls
file1.txt  file2.txt  file3 with space.txt  file_list.txt


$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt                                                        
Hi, I'm file2
Hi, I'm file1
Hi, I'm file3

Таким образом, мы уже выполнили большую часть задачи - мы распечатали все файлы в списке. Остальное просто: перенаправить окончательный вывод в файл с >оператором в итоговый файл.

awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt > output.txt
Сергей Колодяжный
источник