У меня есть список имен файлов в названном файле list_of_files.txt
.
Я хочу скопировать содержание каждого файла в том списке в другой названный файл all_compounds.sdf
.
Как я должен сделать это из командной строки?
Не используйте простую подстановку команд для получения имен файлов (которые могут легко разрываться с пробелами и другими специальными символами). Используйте что-то вроде 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
только на новую строку и отключите globbing (расширение по шаблону):
(set -f; IFS= Окружающие скобки ()
должны запускать это в подоболочке, чтобы эти изменения не повлияли на текущую оболочку.
\n'; cat $(cat list_of_files.txt) > all_compounds.sdf)
Окружающие скобки ()
должны запускать это в подоболочке, чтобы эти изменения не повлияли на текущую оболочку.
Быстрый и грязный путь...
cat $(cat list_of_files.txt) >> all_compounds.sdf
Пожалуйста, примите во внимание: это только работает, если имена файлов в Вашем списке будут очень хорошо вестись себя - то вещи пойдут не так, как надо, если у них будут пробелы, новые строки или любые символы, которые имеют особое значение к оболочке - используют этот ответ вместо этого для надежных результатов),
cat
связывает файлы. Это также печатает их содержание. command2 $(command1)
можно передать вывод command1
(cat list...
) к command2
(cat
) который связывает файлы. Затем используйте перенаправление >>
отправить вывод в файл вместо того, чтобы печатать к stdout. Если Вы хотите видеть вывод, использовать tee
вместо этого:
cat $(cat list_of_files.txt) | tee -a all_compounds.sdf
(Я использовал >>
вместо >
и tee
с -a
переключитесь в случае, если Ваш файл уже существует - это добавляет в файл вместо того, чтобы перезаписать его, если он уже существует),
В то время как 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