Рекурсивно перемещать файлы определенного типа и сохранять их структуру каталогов
У меня есть каталог, который содержит несколько подкаталогов с файлами mov и jpg.
/dir/
/subdir-a/ # contains a-1.jpg, a-2.jpg, a-1.mov
/subdir-b/ # contains b-1.mov
/subdir-c/ # contains c-1.jpg
/subdir-d/ # contains d-1.mov
... # more directories with the same pattern
Мне нужно найти способ использования инструментов командной строки (в идеале для Mac OSX), чтобы переместить все файлы mov в новое место. Однако одним из требований является сохранение структуры каталогов i.e.:
/dir/
/subdir-a/ # contains a-1.mov
/subdir-b/ # contains b-1.mov
# NOTE: subdir-c isn't copied because it doesn't have mov files
/subdir-d/ # contains d-1.mov
...
Я знаком с find
, grep
и xargs
, но не был уверен, как решить эту проблему. Большое спасибо заранее!
Ответы
Ответ 1
Это немного зависит от вашего O/S и, в частности, от возможностей вашей версии tar
и есть ли у вас команда cpio
. Это также немного зависит от того, есть ли у вас новые строки (в частности) в именах файлов; большинство людей этого не делают.
cd /old-dir
find . -name '*.mov' -print | cpio -pvdumB /new-dir
find . -name '*.mov' -print | tar -c -f - -T - |
(cd /new-dir; tar -xf -)
Команда cpio
имеет режим pass-but (copy), который делает именно то, что вам нужно, чтобы указать список имен файлов по одному в строке на его стандартном входе.
В некоторых версиях команды tar
есть возможность читать список имен файлов, по одному на строку, со стандартного ввода; на MacOS X эта опция -T -
(где одиночный -
означает "стандартный ввод" ). Для первой команды tar
параметр -f -
означает (в контексте записи архива с -c
, запись в стандартный вывод); во второй команде tar
параметр -x
означает, что -f -
означает "читать со стандартного ввода".
Могут быть другие варианты; посмотрите на страницу руководства или справьте вывод tar
довольно осторожно.
Этот процесс копирует файлы, а не перемещает их. Вторая половина операции:
find . -name '*.mov' -exec rm -f {} +
Ответ 2
Будучи большими файлами, если они находятся в одной файловой системе, вы не хотите их копировать, а просто для репликации их структуры каталогов во время перемещения.
Вы можете использовать эту функцию:
# moves a file (or folder) preserving its folder structure (relative to source path)
# usage: move_keep_path source destination
move_keep_path () {
# create directories up to one level up
mkdir -p "`dirname "$2"`"
mv "$1" "$2"
}
Или добавив поддержку слияния существующих каталогов:
# moves a file (or folder) preserving its folder structure (relative to source path)
# usage: move_keep_path source destination
move_keep_path () {
# create directories up to one level up
mkdir -p "`dirname "$2"`"
if [[ -d "$1" && -d "$2" ]]; then
# merge existing folder
find "$1" -depth 1 | while read file; do
# call recursively for all files inside
mv_merge "$file" "$2/`basename "$file"`"
done
# remove after merge
rmdir "$1"
else
# either file or non-existing folder
mv "$1" "$2"
fi
}
Ответ 3
из родительского каталога "dir выполните это:
find ./dir -name "*.mov" | xargs tar cif mov.tar
Затем cd в каталог, в который вы хотите переместить файлы, и выполните следующее:
tar xvf /path/to/parent/directory/of"dir"/mov.tar
Ответ 4
ASSERT: в файлах нет символов новой строки. Пространства, однако, являются AOK.
# TEST FIRST: CREATION OF FOLDERS
find . -type f -iname \*.mov -printf '%h\n' | sort | uniq | xargs -n 1 -d '\n' -I '{}' echo mkdir -vp "/TARGET_FOLDER_ROOT/{}"
# EXECUTE CREATION OF EMPTY TARGET FOLDERS
find . -type f -iname \*.mov -printf '%h\n' | sort | uniq | xargs -n 1 -d '\n' -I '{}' mkdir -vp "/TARGET_FOLDER_ROOT/{}"
# TEST FIRST: REVIEW FILES TO BE MOVED
find . -type f -iname \*.mov -exec echo mv {} /TARGET_FOLDER_ROOT/{} \;
# EXECUTE MOVE FILES
find . -type f -iname \*.mov -exec mv {} /TARGET_FOLDER_ROOT/{} \;
Ответ 5
Это должно работать, если вы хотите переместить все файлы mov
в каталог с именем new location -
find ./dir -iname '*.mov' -exec mv '{}' ./newlocation \;
Однако, если вы хотите переместить файлы mov
вместе со своими поддиректорами, вы можете сделать что-то вроде этого -
Шаг 1: Скопируйте всю структуру /dir в новое место, используя cp
cp -iprv dir/ newdir
Шаг 2: найдите jpg
файлы из newdir и удалите их.
find ./newdir -iname "*.jpg" -delete
Тест:
[jaypal:~/Temp] ls -R a
a.mov aa b.mov
a/aa:
aaa c.mov d.mov
a/aa/aaa:
e.mov f.mov
[jaypal:~/Temp] mkdir d
[jaypal:~/Temp] find ./a -iname '*.mov' -exec mv '{}' ./d \;
[jaypal:~/Temp] ls -R d
a.mov b.mov c.mov d.mov e.mov f.mov