Як скопіювати вміст кожного файлу зі списку в інший файл?


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), який об'єднує файли.
  • Потім використовуйте перенаправлення, >>щоб надіслати вихід у файл, а не друкувати в stdout. Якщо ви хочете побачити вихід, використовуйте 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
@ Серг встановив IFS відповідно - див. Останній абзац моєї відповіді
муру

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.