" mv:不能统计"使用find通过xargs移动文件时出错

时间:2014-06-18 11:35:25

标签: bash find xargs stat mv

我正在处理一个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

如果没有办法执行此操作(对于我的脚本中指示的源文件)而不会产生错误?

为什么会生成这些错误(因为文件和文件夹实际上已被移动)?

3 个答案:

答案 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 "{}"  \+

它将解决您的问题。