递归移动某种类型的文件并保留其目录结构

moe*_*oey 14 bash shell command-line grep find

我有一个目录,其中包含多个带有movjpg文件的子目录.

/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
Run Code Online (Sandbox Code Playgroud)

我需要找到一种方法,使用命令行工具(理想情况下在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
  ...
Run Code Online (Sandbox Code Playgroud)

我所熟悉的find,grepxargs,但不知道如何解决这个问题.非常感谢你事先!

Jon*_*ler 18

它略微取决于您的操作系统,更具体地说,取决于您的版本中的设施以及您tar是否拥有该命令cpio.它还取决于你的文件名中是否有换行符(特别是); 大多数人没有.

选项1

cd /old-dir
find . -name '*.mov' -print | cpio -pvdumB /new-dir
Run Code Online (Sandbox Code Playgroud)

选项#2

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

cpio命令具有直通(复制)模式,该模式在标准输入上给出文件名列表(每行一个),它可以完全满足您的要求.

某些版本的tar命令可以选择从标准输入读取文件名列表,每行一个; 在MacOS X上,该选项是-T -(单独-表示'标准输入').对于第一个tar命令,选项-f -意味着(在写入存档的上下文中-c,写入标准输出); 在第二个tar命令中,-x选项-f -意味着"从标准输入读取"的意思.

可能还有其他选择; 请仔细查看手册页或帮助输出tar.

此过程复制文件而不是移动它们.该行动的后半部分将是:

find . -name '*.mov' -exec rm -f {} +
Run Code Online (Sandbox Code Playgroud)

  • 我认为你没有被这个答案所熟悉(特别是cpio部分).与此相比,有30或40个其他stackexchange答案很糟糕 并在此之前出现在谷歌上.你的SEO标准感到羞耻!很棒的答案+1. (2认同)

小智 5

ASSERT:没有文件包含换行符。然而,空格是可以的。

# 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/{} \;
Run Code Online (Sandbox Code Playgroud)