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


34

У меня есть каталог с множеством файлов, например, 50000 PDF-файлов и других файлов на сервере. Мне нужно переместить конкретные в другой каталог. Я могу сгенерировать список файлов, которые должны быть перемещены в CSV или любом другом текстовом формате.

Что мне нужно сделать, это запустить скрипт bash и переместить или скопировать файлы, перечисленные в текстовом файле, в другой каталог.

Есть ли простой способ сделать это? Любые предложения или ресурсы будут с благодарностью.


Кроме того, файлы именуются случайным образом, когда они добавляются в каталог. Не существует соглашения об именах или какой-либо логики, которая могла бы использоваться для перемещения определенных файлов.
Jestep

Ответы:


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
anneb

28

Чтобы избежать бесполезного использования cat(и если вы не используете rsync):

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

Это будет обрабатывать любое допустимое имя файла, если оно не содержит новую строку, если файлы перечислены по одному в строке.


2
Одним из недостатков этого подхода является то, что если файлы в списке содержат имена путей (т.е. они не все находятся в одном и том же каталоге), использование mvприведет к сворачиванию всех их в один и тот же каталог назначения. rsyncПодход в общепринятом ответ не страдает от этого ограничения.
Джейсон Р

Кроме того, я попробовал эту команду, и xargs ломался на любых файлах, содержащих одинарную кавычку («непревзойденная одинарная кавычка»)
Джеймс Бенинджер

Это сработало для меня, потому что я на самом деле хотел файлы из разных исходных путей в одном и том же целевом каталоге.
PseudoNoise

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

предполагая bash, плюс listoffilesсодержащий один файл на строку. Мое единственное возражение против маршрута rsync состоит в том, что OP запрашивает способ перемещения файлов, а не их копирования. В 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 имеет дополнительное преимущество по сравнению с командами cpor, 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, так как tar доступен в базовом образе 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/ В этой строке указывается каталог, отсортированный по возрастанию по дате (обратная сортировка по времени), и отображается дополнительная информация, включая метку даты / времени для каждого файла в теперь загроможденном каталоге назначения. Я обращаюсь к этому, начиная сверху, чтобы показать, какие каталоги и файлы я хочу сохранить там, где они были. В метке даты / времени файлов, где начинаются все новые файлы, будет пробел, которого там быть не должно.

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

vim /opt/dircheck/filestomove Удалите сверху все файлы, которые вы не хотите перемещать.

Затем я использовал команду, указанную ранее в этом посте, чтобы переместить файлы из моего списка в новый каталог, который я создал.

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

Это переместило все файлы за доли секунды. (Примечание: вам может не понадобиться sudo в начале, это вопрос прав доступа к файлам).

Теперь мой исходный каталог назначения хорош и чист и содержит новый каталог со всеми файлами и каталогами, которые его загромождали.


1

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

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

(В общем, смотрите man xargs , это круто )

Если ваш конкретный mv не имеет опции -t, вы также можете сделать некоторые хитрости, такие как

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

Примечание. Ни один из них не будет работать должным образом, если в нем есть имена файлов с символами новой строки.


Тем не мение; смотрите ответ Игнасио, Rsync как бы создан для этого.
Кжетил Йоргенсен

cp, mvИ тому подобное не имеют -tопцию BSD «s, а второй пример с субоболочке не работа для меня ( /path/to/moveприлагается в качестве последнего файла)

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

0

Попробуйте что-то вроде:

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

мог быть while read line; do mv $line /images; done < list.txt как одна команда
игнорирует

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.