Рекурсивно перемещать файлы определенного типа и сохранять их структуру каталогов

у меня есть каталог, который содержит несколько подкаталогов с 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 файлы в новое место. Однако одним из требований является сохранение структуры каталогов, т. е.:

/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 но не знаете, как решить эту проблему. Спасибо очень заблаговременно!

5 ответов


это немного зависит от вашего O / S и, более конкретно, от объектов в вашей версии tar и есть ли у вас команда cpio. Это также зависит от того, есть ли у вас новые строки (в частности) в именах файлов; большинство людей не.

#1

cd /old-dir
find . -name '*.mov' -print | cpio -pvdumB /new-dir

#2

find . -name '*.mov' -print | tar -c -f - -T - |
(cd /new-dir; tar -xf -)

на cpio команда имеет сквозной (копировать) режим, который делает именно то, что вы хотите, учитывая список имена файлов, по одному на строку, на стандартном входе.

некоторые версии есть возможность прочитать список имен файлов по одному на строку из стандартного ввода; на MacOS X, то параметр -T - (где одинокий - означает 'стандартный ввод'). Для первого параметр -f - означает (в контексте написания архиве с -c, напишите к стандартному выходу); во втором на означает, что -f - означает "чтение из стандартного ввода".

могут быть другие варианты; посмотрите на страницу руководства или вывод справки tar довольно тщательно.

этот процесс копирует файлы, а не перемещать их. Вторая половина операции будет:--17-->

find . -name '*.mov' -exec rm -f {} +

будучи большими файлами, если они находятся в одной файловой системе, вы не хотите их копировать, а просто реплицировать их структуру каталогов при перемещении. Вы можете использовать эту функцию:

# 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 ""`"
  mv "" ""
}

или, добавив поддержку слияния существующих каталогах:

# 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 ""`"
  if [[ -d "" && -d "" ]]; then
    # merge existing folder
    find "" -depth 1 | while read file; do
      # call recursively for all files inside
      mv_merge "$file" "/`basename "$file"`"
    done
    # remove after merge
    rmdir ""
  else
    # either file or non-existing folder
    mv "" ""
  fi
}

из родительского каталога " dir выполните это:

find ./dir -name "*.mov" | xargs tar cif mov.tar

затем cd в каталог, в который вы хотите переместить файлы, и выполните следующее:

tar xvf /path/to/parent/directory/of"dir"/mov.tar

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/{} \;

это должно работать, если вы хотите переместить все 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