Linux (mv чи cp) конкретні файли із текстового списку файлів?


34

У мене є каталог багатьох файлів, таких як 50 000 pdf та інших файлів на сервері. Мені потрібно перемістити конкретні в інший каталог. Я можу створити список файлів, які потрібно перемістити або в форматі csv, або в будь-якому іншому текстовому форматі.

Що мені потрібно зробити, це запустити скрипт bash і перемістити або скопіювати файли, перелічені в текстовому файлі, в інший каталог.

Чи є простий спосіб зробити це? Будь-які пропозиції чи ресурси були б вдячні.


Також файли називаються випадковим чином, коли вони додаються до каталогу. Не існує домовленості про іменування або будь-якої логіки, яка могла використовуватись для переміщення конкретних файлів.
Джестеп

Відповіді:


26

Rsync має кілька варіантів , які можуть взяти список файлів для процесу ( --files-from, --include-fromі т.д.).

Наприклад, це зробить трюк:

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

2
приклад:rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
анеб

28

Щоб уникнути марного використання cat(а якщо ви не використовуєте rsync):

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

Це обробляє будь-яке дійсне ім'я файлу, якщо воно не містить новий рядок, якщо файли перераховані один на рядок.


2
Одним із недоліків такого підходу є те, що якщо файли у списку містять імена шляхів (тобто вони не всі в одному каталозі), використання файлів mvбуде згортати їх усіх в один і той же каталог призначення. rsyncПідхід в загальноприйнятому відповідь не страждає від цього обмеження.
Джейсон R

Крім того, я спробував цю команду, і xargs перерветься на будь-які файли, що містять єдину цитату ("неперевершена одна цитата")
Джеймс Бенінгер

Це працювало для мене, тому що я насправді хотів, щоб файли з різних вихідних контурів були в одному цільовому каталозі.
PseudoNoise

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

припускаючи bash, плюс listoffilesмістити один файл у рядку. Моє єдине заперечення щодо маршруту rsync - це те, що ОП запитує спосіб переміщення файлів, а не їх копіювання. У rsync є більше прапорів, ніж на королівському весіллі, тому я впевнений, що це можна додатково змінити, але іноді простіше - краще!


1
Це рішення вважає мене найбільш гнучким. Я в кінцевому рахунку використовував його з rsync замість cp або mv лише тому, що мені потрібна була відносна опція файлових шляхів.
Спамвіч

4
Приємно, просто у мене виникли проблеми з пробілами, тому я змінив його на:while read -r file; do mv "$file" /path/of/destination ; done < listoffiles
user1182474

1
@ user1182474 Спасибі та елегантне використання перенаправлення вводу. Традиційний метод виявлення задоволеності відповіддю - це, до речі, репутація!
MadHatter підтримує Моніку

1
@ user1182474 дякую за це! Останній крок у багатьох модифікаціях довелося дещо сліпо зробити, щоб передати мої утиліти резервного копіювання OSX на мій Android!
Чарлі Горічаназ

4

Це залежить від формату текстового файлу у вас. Наприклад, якщо у вас список файлів написаний таким чином, що кожен файл розташований у новому рядку. Ви можете використовувати xargs як:

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

Крім того, ви можете використовувати findкоманду з -execопцією. копіювати / переміщувати файли.


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

Rsync має додаткову перевагу над командами cpабо, mvоскільки автоматично створює папки, якщо їх не існує.


Навіщо це /path/to/sourceпотрібно, коли воно здійснює шляхи зі списку файлів?
bzero

@bzero, можливо, список файлів може містити відносні шляхи?
Страшна вітер

2

Я думаю, що відповідь rsync є кращою, але просто для іншого варіанту:

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

Це добре для Dockerfile, оскільки смола доступна в базовому зображенні ubuntu, але не rsync.
Крістіанп

1

Я випадково скопіював повний вміст каталогу в каталог призначення замість переміщення повного каталогу. Це призвело до того, що в каталог додається захаращений каталог призначення, а не початковий каталог.

Щоб виправити це, я зробив наступне:

ls -rt /path/to/cluttered/destination/directory/ > /opt/dircheck/filestomove Вищенаведена команда створює файл filestomove, який буде переліком всього вмісту каталогу призначення, зворотним чином відсортованим за часом, тобто найдавнішим до останнього.

Тоді я створив підкаталог тепер забрудненого каталогу призначення для переміщення матеріалів у.

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

Потім я повторив перелік каталогів, за винятком переліку на екран та показу деталей.

ls -lrht /path/to/cluttered/destination/directory/ Цей рядок містить список каталогу, відсортований за датою зростання (зворотний сортування за часом) та показує додаткову інформацію, включаючи штамп дати / часу кожного файлу в теперішньому забитому каталозі призначення. Я посилаюся на це, починаючи вгорі, щоб показати, які каталоги та файли я хочу зберегти там, де вони були. У відмітці дати / часу у файлах буде розрив, де починаються всі нові файли, яких там не повинно бути.

Тоді я відредагував файл, створений на першому етапі вище (який відсортований за датою), і видалив декілька зі списку, які були там раніше, і я хочу залишитися з вихідного каталогу.

vim /opt/dircheck/filestomove Видаліть зверху всі файли, які ви не хочете переміщувати.

Потім я використав команду, перелічену раніше в цій публікації, для переміщення файлів у моєму списку до нового каталогу, який я зробив.

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

Це перемістило всі файли за частку секунди. (Примітка. Судо вам може не знадобитися на початку; це питання дозволу на файли).

Тепер мій оригінальний каталог призначення є приємним та чистим і містить новий каталог із усіма файлами та каталогами, які його захаращували.


1

Якщо (і лише якщо), у файлах файлів не виникає неприємних символів (пробіли, нові рядки, які б переплутали xargs про те, як розбити речі на окремі аргументи), і ви генеруєте список файлів, розділених новими рядками (один файл на рядок), ви могли б зробити щось на кшталт.

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

(Взагалі, дивіться людина xargs , це приголомшливо)

Якщо у вашого конкретного телевізора немає можливості -t, ви також можете зробити деякі хитрощі, як-от

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

Зауважте - жодне з них не працюватиме так, як очікувалося, якщо трапляються назви файлів з новими рядками в них.


Однак; див. відповідь Ігнасіо, rsync створений для цього матеріалу.
Kjetil Joergensen

cp, mvі подібні не мають -tопції на bsd 's, а другий приклад з subshell не працював для мене ( /path/to/moveдодається як останнє ім'я файлу)

1
@ w17t - звучить як filenames.txt не закінчується новим рядком, або додайте новий рядок до кінця filenames.txt, або зробіть щось на кшталт(cat filenames.txt; echo; echo /path/to/move/files/to) | xargs mv
Kjetil Joergensen

0

Спробуйте щось на кшталт:

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

міг бути while read line; do mv $line /images; done < list.txt як одна команда
ignivs

0

Наступне працювало для мене, де мені потрібно було скопіювати всі файли PNG з певного шляху (і всіх підкаталогів) на нове місце, зберігаючи структуру каталогу:

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

Оскільки RSYNC спочатку створює дзеркало структури каталогів, а потім синхронізує файли, ви можете закінчити порожні папки, які порожні. Я використовував прапор --prune-empty-dirs для видалення цих порожніх каталогів.

Я не маю ніякої приналежності, але вважав за правильне віддати джерело, яке надихнуло це рішення: http://techblog.zabuchy.net/2011/transfer-only-selected-file-types-with-rsync/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.