我正在处理一个bash脚本,该脚本需要(递归地)将源文件夹中的所有文件和文件夹移动到目标文件夹中。
在尝试尽可能强大并且解决潜在问题argument list too long - errors时,我选择使用find
命令(以安全地确定要移动的文件)传送到xargs
(有效地将动作分组在一起)。我还使用-print0
和-0
来解决空间的潜在问题。
我已经编写了以下测试脚本:
#!/bin/bash
# create test source file structure, and destination folder
mkdir -p sourceDir/{subdir1,subdir\ with\ space\ 2}
mkdir -p destDir
touch sourceDir/subdir1/{a1.txt,noExtension1,file1\ with\ space.txt}
touch sourceDir/subdir\ with\ space\ 2/{a2.txt,noExtension2,file2\ with\ space.txt}
#move files/folders from source to destination
find sourceDir -mindepth 1 -print0 | xargs -0 mv --target-directory=destDir
这似乎有用(即文件被移动)但由于某种原因我收到如下错误:
mv: cannot stat `sourceDir/subdir with space 2/file2 with space.txt': No such file or directory
mv: cannot stat `sourceDir/subdir with space 2/noExtension2': No such file or directory
mv: cannot stat `sourceDir/subdir with space 2/a2.txt': No such file or directory
mv: cannot stat `sourceDir/subdir1/file1 with space.txt': No such file or directory
mv: cannot stat `sourceDir/subdir1/noExtension1': No such file or directory
mv: cannot stat `sourceDir/subdir1/a1.txt': No such file or directory
如果没有办法执行此操作(对于我的脚本中指示的源文件)而不会产生错误?
为什么会生成这些错误(因为文件和文件夹实际上已被移动)?
答案 0 :(得分:1)
我已经怀疑了。
简答:我错过了-maxdepth 1
标记。以下命令有效
find sourceDir -mindepth 1 -maxdepth 1 -print0 | xargs -0 mv --target-directory=destDir
# as does
find sourceDir -mindepth 1 -maxdepth 1 -exec mv --target-directory=destDir '{}' +
更长的回答:
我的原始find命令列出了每个文件的路径,然后尝试移动它们中的每一个。移动顶级文件夹后,无需移动任何文件/文件夹 - 但脚本仍在尝试!
下面的脚本演示了这一点(没有实际执行移动):
#!/bin/bash
mkdir -p sourceDir/{subdir1/subsubdir1,subdir\ with\ space\ 2}
touch sourceDir/subdir1/{subsubdir1/deeperFile.log,a1.txt,noExtension1,file1\ with\ space.txt}
touch sourceDir/subdir\ with\ space\ 2/{a2.txt,noExtension2,file2\ with\ space.txt}
touch sourceDir/rootFile.txt
echo -e "\n--- Output of 'ls -1: sourceDir':"
echo "$(ls -1 sourceDir)"
echo -e "\n--- original incorrect attempt was trying to move each of the following:"
find sourceDir -mindepth 1
echo -e "\n--- working attempt only needs to move each of the top level files/folders, everything underneath any folders will get moved automatically"
find sourceDir -mindepth 1 -maxdepth 1
给出输出:
--- Output of 'ls -1: sourceDir':
rootFile.txt
subdir1
subdir with space 2
--- original incorrect attempt was trying to move each of the following:
sourceDir/rootFile.txt
sourceDir/subdir with space 2
sourceDir/subdir with space 2/file2 with space.txt
sourceDir/subdir with space 2/noExtension2
sourceDir/subdir with space 2/a2.txt
sourceDir/subdir1
sourceDir/subdir1/file1 with space.txt
sourceDir/subdir1/noExtension1
sourceDir/subdir1/a1.txt
sourceDir/subdir1/subsubdir1
sourceDir/subdir1/subsubdir1/deeperFile.log
--- working attempt only needs to move each of the top level files/folders, everything underneath any folders will get moved automatically
sourceDir/rootFile.txt
sourceDir/subdir with space 2
sourceDir/subdir1
答案 1 :(得分:0)
为什么不直接使用find
命令?
$ find [...] -exec mv '{}' [...] ';'
其中{}
表示找到每个文件,;
传递给mv
的参数结尾
答案 2 :(得分:0)
默认情况下,find命令的输出以父目录开头,然后目录包含。
directroy结构上的简单查找命令提供以下输出:
sourceDir/subdir1
sourceDir/subdir1/a1.txt
sourceDir/subdir1/noExtension1
sourceDir/subdir1/file1 with space.txt
sourceDir/subdir with space 2
sourceDir/subdir with space 2/noExtension2
sourceDir/subdir with space 2/file2 with space.txt
如果在xargs
或-exec
中使用此输出,它将首先处理父目录,然后处理其内容。在这种情况下,您的命令执行正常并将所有sourceDir / subdir1目录移动到destDir / subdire1。之后,sourceDir中没有sourceDir / subdir1 / a1.txt或sourceDir / subdir1 / noExtension1等文件/目录,因为它已经移动到destDir。
要避免使用-depth
选项。
-depth Process each directory's contents before the directory itself.
在您的情况下,您可以添加-type d
选项以将顶级源目录移动到destDir。
find sourceDir -mindepth 1 -type d -print0 | xargs -0 mv --target-directory=destDir
或
find sourceDir -mindepth 1 -type d -exec mv -t destDir "{}" \+
它将解决您的问题。