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.
Odpowiedzi:
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ę:
źródło
rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
Aby uniknąć bezużytecznego korzystania z
cat
(a jeśli nie korzystaszrsync
):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.
źródło
mv
zwinie je wszystkie w tym samym katalogu docelowym.rsync
Podejście w przyjętym odpowiedź nie cierpi z tego ograniczenia.zakładając bash, plus
listoffiles
zawierają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!źródło
while read -r file; do mv "$file" /path/of/destination ; done < listoffiles
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:
Możesz także użyć
find
polecenia z-exec
opcją. aby skopiować / przenieść pliki.źródło
Rsync ma dodatkową zaletę nad poleceniami
cp
lubmv
, ponieważ automatycznie utworzy foldery, jeśli nie istnieją.źródło
/path/to/source
potrzebny, gdy pobiera ścieżki z listy plików?Myślę, że odpowiedź rsync jest lepsza, ale tylko dla innej opcji:
źródło
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.
źródło
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.
(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
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.
źródło
cp
,mv
i tym podobne nie mają-t
opcji na bsd , a drugi przykład z podpowłoką nie działał dla mnie (/path/to/move
jest dołączany jako ostatnia nazwa pliku)(cat filenames.txt; echo; echo /path/to/move/files/to) | xargs mv
Wypróbuj coś takiego:
źródło
while read line; do mv $line /images; done < list.txt
jednym poleceniemPoniż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:
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/
źródło