Pliki specyficzne dla systemu Linux (mv lub cp) z tekstowej listy plików?


34

Mam katalog wielu plików, około 50 000 plików pdf i innych plików na serwerze. Muszę przenieść określone do innego katalogu. Mogę wygenerować listę plików, które należy przenieść w formacie csv lub innym formacie tekstowym.

Muszę uruchomić skrypt bash i przenieść lub skopiować pliki wymienione w pliku tekstowym do innego katalogu.

Czy jest na to prosty sposób? Wszelkie sugestie lub zasoby będą mile widziane.


Ponadto pliki są nazywane losowo po dodaniu do katalogu. Nie ma konwencji nazewnictwa ani logiki, która mogłaby zostać wykorzystana do przeniesienia określonych plików.
Jestep

Odpowiedzi:


26

rsync ma kilka opcji, które mogą wziąć listę plików do procesu ( --files-from, --include-from, itd.).

Na przykład to załatwi sprawę:

rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory

2
przykład:rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
anneb

28

Aby uniknąć bezużytecznego korzystania z cat(a jeśli nie korzystasz rsync):

xargs -a file_list.txt mv -t /path/to/dest

Będzie to obsługiwać każdą prawidłową nazwę pliku, chyba że zawiera on nowy wiersz, jeśli pliki są wymienione po jednym w wierszu.


2
Jedną wadą tego podejścia jest to, że jeśli pliki na liście zawierają nazwy ścieżek (tzn. Nie wszystkie znajdują się w tym samym katalogu), użycie opcji mvzwinie je wszystkie w tym samym katalogu docelowym. rsyncPodejście w przyjętym odpowiedź nie cierpi z tego ograniczenia.
Jason R

Próbowałem także tego polecenia, a xargs zepsułby się na plikach zawierających pojedynczy cytat („niedopasowany pojedynczy cytat”)
James Beninger,

To działało dla mnie, ponieważ tak naprawdę chciałem pliki z różnych ścieżek źródłowych w tym samym katalogu docelowym.
PseudoNoise

15
for file in `cat listoffiles`; do mv "$file" /path/of/destination ; done

zakładając bash, plus listoffileszawierający jeden plik w linii. Jedyny mój sprzeciw wobec trasy rsync polega na tym, że OP prosi o metodę przenoszenia plików, a nie ich kopiowania. rsync ma więcej flag niż królewski ślub, więc jestem pewien, że można to jeszcze zmodyfikować, ale czasem prostsze jest lepsze!


1
To rozwiązanie wydaje mi się najbardziej elastyczne. Skończyło się na tym, że używałem rsync zamiast cp lub mv tylko dlatego, że potrzebowałem opcji względnych ścieżek plików.
Spamwich,

4
Fajnie, po prostu miałem problemy ze spacjami, więc zmodyfikowałem go do:while read -r file; do mv "$file" /path/of/destination ; done < listoffiles
user1182474

1
@ user1182474 Dzięki i eleganckie wykorzystanie przekierowania wejściowego. Nawiasem mówiąc, tradycyjną metodą okazania satysfakcji z odpowiedzi jest głosowanie!
MadHatter obsługuje Monikę

1
@ user1182474 dziękuję za to! ostatnim krokiem w wielu modyfikacjach było nieco ślepe dokonanie przeniesienia narzędzi do tworzenia kopii zapasowych OSX na Androida!
Charlie Gorichanaz

4

Zależy to od formatu posiadanego pliku tekstowego. Na przykład, jeśli masz listę plików zapisanych w taki sposób, że każdy plik znajduje się w nowym wierszu. Możesz używać xargs takich jak:

$ cat your_text_file | xargs cp -t /path/to/destination

Możesz także użyć findpolecenia z -execopcją. aby skopiować / przenieść pliki.


3
rsync --files-from=file_list.txt /path/to/source/ /path/to/dest/

Rsync ma dodatkową zaletę nad poleceniami cplub mv, ponieważ automatycznie utworzy foldery, jeśli nie istnieją.


Dlaczego jest /path/to/sourcepotrzebny, gdy pobiera ścieżki z listy plików?
bzero

@bzero może lista plików może zawierać ścieżki względne?
DreadfulWeather

2

Myślę, że odpowiedź rsync jest lepsza, ale tylko dla innej opcji:

tar -cf - -T FILE_OF_FILENAMES_TO_MOVE.txt |(cd /path/to/new/dir && tar -xvf -)

Jest to dobre dla pliku Docker, ponieważ tar jest dostępny w podstawowym obrazie ubuntu, ale nie rsync.
kristianp

1

Przypadkowo skopiowałem całą zawartość katalogu do katalogu docelowego zamiast przenosić pełny katalog. Spowodowało to zaśmiecenie katalogu docelowego zamiast dodawania katalogu źródłowego do katalogu.

Aby to naprawić, wykonałem następujące czynności:

ls -rt /path/to/cluttered/destination/directory/ > /opt/dircheck/filestomove Powyższe polecenie tworzy plik filestomove, który będzie listą całej zawartości katalogu docelowego, posortowaną odwrotnie według czasu, co oznacza najstarszą do najnowszej.

Następnie utworzyłem podkatalog już zaśmieconego katalogu docelowego, do którego można przenieść rzeczy.

mkdir /path/to/cluttered/destination/directory/newsubdirectory

Następnie powtórzyłem listę katalogów, z wyjątkiem listy do ekranu i pokazania więcej szczegółów.

ls -lrht /path/to/cluttered/destination/directory/ W tym wierszu znajduje się katalog, posortowany według daty rosnąco (sortowanie wstecz według czasu) i pokazuje więcej informacji, w tym znacznik daty / godziny każdego pliku w zaśmieconym katalogu docelowym. Odnoszę się do tego, zaczynając od góry, aby pokazać, które katalogi i pliki chcę zachować tam, gdzie były. W datach / czasach plików będzie luka, w której zaczynają się wszystkie nowe pliki, których nie powinno tam być.

Następnie zredagowałem plik filestomove utworzony w pierwszym kroku powyżej (posortowanym według daty) i usunąłem kilka z listy, które były tam wcześniej, które chcę pozostać w oryginalnym katalogu.

vim /opt/dircheck/filestomove Usuń z góry wszystkie pliki, których nie chcesz przenosić.

Następnie użyłem polecenia wymienionego wcześniej w tym poście, aby przenieść pliki z mojej listy do nowego katalogu, który utworzyłem.

sudo xargs -a /opt/dircheck/filestomove mv -t /path/to/cluttered/destination/directory/newsubdirectory

To spowodowało przeniesienie wszystkich plików w ułamku sekundy. (Uwaga: sudo może nie być potrzebne na początku, jest to kwestia uprawnień do plików).

Teraz mój oryginalny katalog docelowy jest ładny i czysty i zawiera nowy katalog ze wszystkimi plikami i katalogami, które go zagracały.


1

Jeśli (i tylko jeśli), nie masz żadnych nieprzyjemnych znaków w nazwach plików (spacje, znaki nowej linii, które wprowadzałyby w błąd xargs dotyczące sposobu dzielenia rzeczy na poszczególne argumenty), i generujesz listę plików oddzielonych znakami nowej linii (jeden plik na linię), możesz zrobić coś takiego.

cat filenames.txt | xargs mv -t /path/to/move/files/to

(Ogólnie rzecz biorąc, zobacz man xargs , jest niesamowity)

Jeśli twój konkretny mv nie ma opcji -t, możesz również zrobić sztuczki, takie jak

( cat filenames.txt; echo; echo /path/to/move/files/to ) | xargs mv

Uwaga - żadne z nich nie będzie działać zgodnie z oczekiwaniami, jeśli zdarzy się, że będą nazwy plików z nowymi liniami.


Jednak; zobacz odpowiedź Ignacio, rsync jest w pewnym sensie stworzony do tego.
Kjetil Joergensen,

cp, mvi tym podobne nie mają -topcji na bsd , a drugi przykład z podpowłoką nie działał dla mnie ( /path/to/movejest dołączany jako ostatnia nazwa pliku)

1
@ w17t - brzmi jak nazwa_pliku.txt nie kończy się znakiem nowej linii, albo dodaj znak nowej linii na końcu pliku nazwa_pliku.txt, albo zrób coś takiego(cat filenames.txt; echo; echo /path/to/move/files/to) | xargs mv
Kjetil Joergensen

0

Wypróbuj coś takiego:

cat list.txt | while read line; do mv "$line" /images; done

mogło być while read line; do mv $line /images; done < list.txt jednym poleceniem
ignivs

0

Poniższe działało dla mnie, gdzie musiałem skopiować wszystkie pliki PNG z określonej ścieżki (i wszystkich podkatalogów) do nowej lokalizacji, zachowując jednocześnie strukturę katalogów:

rsync -av --prune-empty-dirs --include='*/' --include='*.png' --exclude='*' source/ destination/

Ponieważ RSYNC najpierw tworzy kopię lustrzaną struktury katalogów, a następnie synchronizuje pliki, możesz uzyskać nadmiar folderów, które są puste. Użyłem flagi --prune-empty-dirs, aby usunąć te puste katalogi.

Nie mam przynależności, ale uznałem za słuszne uznanie źródła, które zainspirowało to rozwiązanie: http://techblog.zabuchy.net/2011/transfer-only-selected-file-types-with-rsync/

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.