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