Wcześniej otrzymałem wstydliwą odpowiedź, ale Odpowiedź Denisa przypomniałem mi, że przegapiłem najbardziej podstawową rzecz. Więc usunąłem moją oryginalną odpowiedź. Ale ponieważ nikt nie ma powiedziany ta bardzo podstawowa rzecz, myślę, że warto ją tutaj umieścić.
Pierwotne pytanie brzmi: „Mam plik tekstowy z listą nazw plików rozdzielonych spacjami. Jak mogę skopiować je do jednego katalogu docelowego”. Na początku może się to wydawać trudne lub skomplikowane, ponieważ uważasz, że musisz w jakiś sposób wyodrębnić elementy z pliku w określony sposób. Jednak gdy powłoka przetwarza wiersz poleceń, pierwszą rzeczą, którą robi, jest rozdziel listę argumentów na tokeny i (tu jest coś, czego nikt nie powiedział wprost) spacje oddzielne żetony . (Newlines również oddzielają tokeny, dlatego test Douga Harrisa z rozdzieloną listą linii miał taki sam wynik.) Oznacza to, że powłoka oczekuje i może już obsługiwać listę oddzieloną spacjami.
Wszystko, co musisz tutaj zrobić, to umieścić rozdzieloną spacjami listę (którą już masz) we właściwym miejscu w swoim poleceniu. Twoje polecenie to pewna odmiana tego:
cp file1 file2 file3...file# target
Jedyną zmarszczką jest to, że chcesz pobrać listę plików 1 do # z pliku tekstowego.
Jak podkreśla Dennis w swoim komentarzu, twoja oryginalna próba ( cp
cat list.txt new_folder
) powinien już działać. Czemu? Ponieważ polecenie wewnętrzne cat list.txt
jest przetwarzany najpierw przez powłokę i rozwija się w file1 file2 file3...file#
, co jest dokładnie tym, czego powłoka oczekuje i chce w tej części polecenia. Jeśli to nie zadziałało, albo (1) miałeś literówkę, albo (2) twoje nazwy plików były w jakiś sposób dziwne (miały spacje lub inne niezwykłe znaki).
Powodem, dla którego wszystkie odpowiedzi Dennisa działają, jest po prostu dostarczenie niezbędnej listy plików cp
pracować nad umieszczeniem tej listy tam, gdzie należy do całego polecenia. Ponownie samo polecenie ma taką strukturę:
cp list-of-files target_directory
Łatwo jest zobaczyć, jak to wszystko łączy się w tej wersji:
cp $(<list.txt) new_folder
$()
powoduje, że powłoka uruchamia polecenie wewnątrz nawiasów, a następnie zastępuje jego wyjście w tym punkcie większej linii. Następnie powłoka uruchamia linię jako całość. Tak poza tym, $()
jest bardziej nowoczesną wersją tego, co robiłeś już z backticks (`). Kolejny: <
jest operatorem przekierowania plików. Mówi powłoce, aby zrzucił zawartość list.txt
na standardowe wejście. Od $()
bit jest przetwarzany najpierw, oto co dzieje się etapami:
cp $(<list.txt) new_folder
# split line into three tokens: cp, $(<list.txt), new_folder
cp file1 file2 file3...file# new_folder
# substitute result of $(<list.txt) into the larger command
Oczywiście krok 2 jest po prostu normalny cp
rozkaz, który chciałeś.
Zdaję sobie sprawę, że często pokonuję tego (być może bardzo martwego) konia, ale myślę, że warto to robić. Zrozumienie dokładnie w jaki sposób powłoka przetwarza polecenie może pomóc ci lepiej napisać i uprościć. Pokaże również, gdzie mogą się ukrywać problemy. W tym przypadku na przykład moje pierwsze pytanie powinno dotyczyć zabawnych nazw plików lub literówki. Żadne akrobacje nie były konieczne.