bash 递归移动某种类型的文件并保持它们的目录结构
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8798153/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Recursively move files of certain type and keep their directory structure
提问by moey
I have a directory which contains multiple sub-directories with movand jpgfiles.
我有一个目录,其中包含多个带有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
I need to find a way using command-line tools (on Mac OSX, ideally) to move all the movfiles to a new location. However, one requirement is to keep directory structure i.e.:
我需要找到一种使用命令行工具(在 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
...
I am familiar with find, grep, and xargsbut wasn't sure how to solve this issue. Thank you very much beforehand!
我熟悉find, grep,xargs但不确定如何解决此问题。事先非常感谢!
回答by Jonathan Leffler
It depends slightly on your O/S and, more particularly, on the facilities in your version of tarand whether you have the command cpio. It also depends a bit on whether you have newlines (in particular) in your file names; most people don't.
这在一定程度上取决于您的操作系统,更具体地说,取决于您的版本中的设施以及您tar是否拥有命令cpio. 它还取决于您的文件名中是否有换行符(特别是);大多数人没有。
Option #1
选项1
cd /old-dir
find . -name '*.mov' -print | cpio -pvdumB /new-dir
Option #2
选项#2
find . -name '*.mov' -print | tar -c -f - -T - |
(cd /new-dir; tar -xf -)
The cpiocommand has a pass-through (copy) mode which does exactly what you want given a list of file names, one per line, on its standard input.
该cpio命令具有传递(复制)模式,在其标准输入上,给定一个文件名列表,每行一个,该模式正是您想要的。
Some versions of the tarcommand have an option to read the list of file names, one per line, from standard input; on MacOS X, that option is -T -(where the lone -means 'standard input'). For the first tarcommand, the option -f -means (in the context of writing an archive with -c, write to standard output); in the second tarcommand, the -xoption means that the -f -means 'read from standard input'.
某些版本的tar命令可以选择从标准输入读取文件名列表,每行一个;在 MacOS X 上,该选项是-T -(其中唯一的-意思是“标准输入”)。对于第一个tar命令,该选项-f -意味着(在使用 写入存档的上下文中-c,写入标准输出);在第二个tar命令中,该-x选项的意思-f -是“从标准输入读取”。
There may be other options; look at the manual page or help output of tarrather carefully.
可能还有其他选择;tar相当仔细地看手册页或帮助输出。
This process copies the files rather than moving them. The second half of the operation would be:
此过程复制文件而不是移动它们。操作的后半部分将是:
find . -name '*.mov' -exec rm -f {} +
回答by djjeck
Being large files, if they are on the same file system you don't want to copy them, but just to replicate their directory structure while moving. You can use this function:
作为大文件,如果它们在同一个文件系统上,您不想复制它们,而只是在移动时复制它们的目录结构。您可以使用此功能:
# 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 "" ""
}
Or, adding support to merging existing directories:
或者,添加对合并现有目录的支持:
# 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
}
回答by bshensky
ASSERT: No files have newline characters in them. Spaces, however, are 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/{} \;
回答by ennuikiller
from the parent directory of "dir execute this:
从“dir”的父目录执行:
find ./dir -name "*.mov" | xargs tar cif mov.tar
Then cd to the directory you want to move the files to and execute this:
然后 cd 到您要将文件移动到的目录并执行以下命令:
tar xvf /path/to/parent/directory/of"dir"/mov.tar
回答by jaypal singh
This should work if you want to move all movfiles to a directory called new location -
如果您想将所有mov文件移动到名为新位置的目录,这应该可以工作-
find ./dir -iname '*.mov' -exec mv '{}' ./newlocation \;
However, if you wish to move the movfiles along with their sub-dirs then you can do something like this -
但是,如果您希望将mov文件与其子目录一起移动,那么您可以执行以下操作 -
Step 1: Copy entire structure of /dir to a new location using cp
第 1 步:使用以下命令将 /dir 的整个结构复制到新位置 cp
cp -iprv dir/ newdir
Step 2: Find jpgfiles from newdir and delete them.
第 2 步:jpg从 newdir 中查找文件并删除它们。
find ./newdir -iname "*.jpg" -delete
Test:
测试:
[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
回答by robodo
It is easier to just copy the files like:
复制以下文件更容易:
cp --parents some/folder/*/*.mov new_folder/

