У мене є список імен файлів у файлі під назвою 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
Зверніть увагу: це працює лише в тому випадку, якщо файли у вашому списку ведуться дуже добре - все піде не так, якщо у них є пробіли, нові рядки або будь-які символи, які мають особливе значення для оболонки - використовуйте цю відповідь замість для надійних результатів)
catcon 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)"