У мене є список імен файлів у файлі під назвою 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
), який об'єднує файли.Потім використовуйте перенаправлення, >>
щоб надіслати вихід у файл, а не друкувати в stdout. Якщо ви хочете побачити вихід, використовуйте 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)"