Jak skopiować zawartość każdego pliku z listy do innego pliku?

15

Mam listę nazw plików w pliku o nazwie list_of_files.txt.

Chcę skopiować zawartość każdego pliku z tej listy do innego pliku o nazwie all_compounds.sdf.

Jak mam to zrobić z wiersza poleceń?

Ramita Rajaa
źródło

Odpowiedzi:

20

Nie używaj prostego zastępowania poleceń, aby uzyskać nazwy plików (które mogłyby łatwo zerwać ze spacjami i innymi znakami specjalnymi). Użyj czegoś takiego xargs:

xargs -d '\n' -a list_of_files.txt cat > all_compounds.sdf

Lub while readpętla:

while IFS= read -r file; do cat "$file"; done < list_of_files.txt > all_compounds.sdf

Aby bezpiecznie korzystać z podstawiania poleceń, ustaw przynajmniej IFSnową linię i wyłącz globowanie (rozwijanie symboli wieloznacznych):

(set -f; IFS=$'\n'; cat $(cat list_of_files.txt) > all_compounds.sdf)

Nawias otaczający ()powinien uruchomić to w podpowłoce, aby te zmiany nie wpłynęły na twoją bieżącą powłokę.

muru
źródło
14

Szybki i brudny sposób ...

cat $(cat list_of_files.txt) >> all_compounds.sdf

Uwaga: działa to tylko wtedy, gdy nazwy plików na liście są bardzo dobrze zachowane - wszystko pójdzie źle, jeśli będą miały spacje, znaki nowej linii lub znaki mające specjalne znaczenie dla powłoki - użyj tej odpowiedzi, aby uzyskać wiarygodne wyniki)

Notatki

  • catcon cat tworzy pliki. Drukuje również ich zawartość.
  • Używając podstawiania poleceń command2 $(command1), możesz przekazać dane wyjściowe command1( cat list...) na command2( cat), które łączą pliki.
  • Następnie użyj przekierowania, >>aby wysłać dane wyjściowe do pliku zamiast drukowania na standardowe wyjście. Jeśli chcesz zobaczyć wynik, użyj teezamiast tego:

    cat $(cat list_of_files.txt) | tee -a all_compounds.sdf

(Użyłem >>zamiast >i teez -aprzełącznikiem, jeśli Twój plik już istnieje - to dołącza się do pliku zamiast nadpisywać go, jeśli już istnieje)

Zanna
źródło
1
@Zanna zacytował podstawienia poleceń, aby uniknąć podziału słów, jak"$(cat list_of_files.txt)"
Sergiy Kolodyazhnyy
4
@Serg, jeśli dzielenie słów nie zostało wykonane, a następnie catpobiera całą listę jako jeden argument.
muru
@muru OK, jak zatem postępować z nazwami plików zawierającymi spacje?
Sergiy Kolodyazhnyy
1
@Serg odpowiednio ustaw IFS - patrz ostatni akapit mojej odpowiedzi
muru
4

Chociaż GNU awkjest narzędziem do przetwarzania tekstu, pozwala na uruchamianie zewnętrznych poleceń powłoki poprzez system()wywołanie. Możemy to wykorzystać na naszą korzyść:

$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt                                                        

Pomysł jest prosty: odczytujemy plik linia po linii i z każdej linii tworzymy sformatowany ciąg cat "File name.txt", który jest następnie przekazywany do system().

I oto jest w akcji:

$ 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

Tak więc wykonaliśmy już dużą część zadania - wydrukowaliśmy wszystkie pliki z listy. Reszta jest prosta: przekieruj ostateczne wyjście do pliku z >operatorem do pliku podsumowania.

awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt > output.txt
Sergiy Kolodyazhnyy
źródło