Mam listę plików oddzielonych spacjami w pliku list.txt
. Chciałbym skopiować je do nowego folderu.
Próbowałem to zrobić:
cp `cat list.txt` new_folder
ale to nie zadziałało.
Jak byś to zrobił?
Aktualizacja:
Dziękuję za wszystkie bardzo interesujące odpowiedzi. Nie prosiłem o to za dużo :)
Po wypróbowaniu rozwiązania powyżej po raz drugi wydaje się, że cp
wydrukował pomoc dotyczącą użytkowania, ponieważ folder new_folder
jeszcze nie istniał! Niestety, wydaje się, że to głupi błąd ... Kiedy tworzę folder wcześniej, działa.
Nauczyłem się jednak wiele ze wszystkich odpowiedzi i rozwiązań, dziękuję za poświęcony czas na ich napisanie.
Odpowiedzi:
Spróbuj użyć xargs:
Aktualizacja:
Zrobiłem to na OS X, który ma inną wersję niż wersje GNU / Linux. The
xargs
który pochodzi z GNU findutils nie ma-J
ale tak jest-I
co jest podobne (jak zauważył Dennis Williamson w komentarzu). Wersja xargs systemu OS X ma obie wersje-I
i-J
które mają nieco inne zachowania - albo będą działać dla tego oryginalnego pytania.źródło
xargs
nie ma-J
to ma-I
który wydaje się robić to samo. Jaka wersjaxargs
a jaki masz system operacyjny / dystrybucję?xargs --version
zwraca komunikat o błędzie użycia. Prawdopodobnie jest to wersja xargs BSD. Sposób użycia-I
i-J
są nieco inne. Zaktualizuję moją odpowiedź ładnie sformatowanymi przykładami.-J
i-I
:)Nie ma potrzeby
cat
w ogóle:Lub używając długich opcji:
Oto kilka wersji powłoki:
Grzmotnąć:
lub
sh (lub Bash):
lub
lub
lub
źródło
-t
potrzebne wxargs -a list.txt cp -t new_folder
?-t
jest opcjacp
. Kopiuje wszystkie argumenty źródłowe do określonego katalogu docelowego. Tutaj pozwala na określenie celu przed źródłem dodanym przezxargs
dowództwo.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:
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.txtnew_folder
) powinien już działać. Czemu? Ponieważ polecenie wewnętrznecat list.txt
jest przetwarzany najpierw przez powłokę i rozwija się wfile1 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ę:Łatwo jest zobaczyć, jak to wszystko łączy się w tej wersji:
$()
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.
źródło
--parents
flaga. Możesz sprawić, że będzie gadatliwy-v
dla zapisu tego, co zostało skopiowane. Jeśli chcesz zachować uprawnienia, potrzebujesz-a
lub-p
flaga. To znaczy,cp --parents -av $(<list.txt) new_folder
. To wszystko zakłada, że twoja lista plików to w rzeczywistości wszystkie pliki, w przeciwnym razie możesz również potrzebować-r
flaga do powtórzenia.--parents
flaga tam nie istnieje. Ich (pochodząca z BSD) wersjacp
udostępnia tylko krótkie opcje, a nie długie opcje w stylu GNU. Dla stylu BSDcp
, flaga dla kopii rekurencyjnej jest wielka-R
, nie małe litery.