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

У меня есть каталог, который содержит несколько подкаталогов с файлами 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, но не знал, как решитьЭта проблема.Заранее большое спасибо!

Ответы [ 6 ]

17 голосов
/ 10 января 2012

Это немного зависит от вашей операционной системы и, в частности, от возможностей вашей версии 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 имеет режим сквозного копирования (копирования), который делает именно то, что вы хотите, учитывая список имен файлов, по одному на строку, на своем стандартном вводе.

В некоторых версиях команды tar есть опция для чтения списка имен файлов, по одному на строку, из стандартного ввода; в MacOS X эта опция -T - (где lone - означает «стандартный ввод»). Для первой команды tar опция -f - означает (в контексте записи архива с -c, запись в стандартный вывод); во второй команде tar опция -x означает, что -f - означает «чтение из стандартного ввода».

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

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

find . -name '*.mov' -exec rm -f {} +
3 голосов
/ 31 декабря 2012

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

# 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
}
1 голос
/ 12 октября 2014

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/{} \;
1 голос
/ 10 января 2012

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

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

Затем перейдите в каталог, в который вы хотите переместить файлы, и выполните это:

tar xvf /path/to/parent/directory/of"dir"/mov.tar
0 голосов
/ 30 марта 2019

Проще скопировать файлы, например:

cp --parents some/folder/*/*.mov new_folder/
0 голосов
/ 10 января 2012

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