我有一个目录,其中包含多个带 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
, and xargs
,但不知道如何解决这个问题。非常感谢你!
答案 0 :(得分:17)
这取决于您的操作系统,更具体地说,取决于您的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 -
(单独-
表示'标准输入')。对于第一个tar
命令,选项-f -
表示(在使用-c
编写存档的上下文中,写入标准输出);在第二个tar
命令中,-x
选项表示-f -
表示“从标准输入中读取”。
可能还有其他选择;请仔细查看手册页或帮助tar
的输出。
此过程复制文件而不是移动文件。该行动的后半部分将是:
find . -name '*.mov' -exec rm -f {} +
答案 1 :(得分:3)
作为大文件,如果它们位于同一文件系统上,则您不想复制它们,而只是在移动时复制其目录结构。 您可以使用此功能:
# 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
}
答案 2 :(得分:1)
来自“目录”的父目录执行此命令:
find ./dir -name "*.mov" | xargs tar cif mov.tar
然后cd到要移动文件的目录并执行:
tar xvf /path/to/parent/directory/of"dir"/mov.tar
答案 3 :(得分:1)
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/{} \;
答案 4 :(得分:0)
如果要将所有mov
文件移动到名为new location -
find ./dir -iname '*.mov' -exec mv '{}' ./newlocation \;
但是,如果您希望将mov
文件与其子目录一起移动,那么您可以执行以下操作 -
cp
cp -iprv dir/ newdir
jpg
个文件并删除它们。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
答案 5 :(得分:0)
仅复制以下文件会更容易:
cp --parents some/folder/*/*.mov new_folder/
答案 6 :(得分:0)
我修改了@djjeck 的功能,因为它没有按我的需要工作。下面的函数将源文件移动到目标目录,同时在源文件路径中创建所需的层次结构级别(参见下面的示例):
# moves a file, creates needed levels of hierarchy in destination
# usage: move_with_hierarchy source_file destination top_level_directory
move_with_hierarchy () {
path_tail=$(dirname $(realpath --relative-to="$3" "$1"))
cd "$2"
mkdir -p $path_tail
cd - > /dev/null
mv "$1" "${2}/${path_tail}"
}
示例:
$ ls /home/sergei/tmp/dir1/dir2/bla.txt
/home/sergei/tmp/dir1/dir2/bla.txt
$ rm -rf tmp2
$ mkdir tmp2
$ move_with_hierarchy /home/sergei/tmp/dir1/dir2/bla.txt /home/sergei/tmp2 /home/sergei/tmp
$ tree ~/tmp2
/home/sergei/tmp2
└── dir1
└── dir2
└── bla.txt
2 directories, 1 file