mv: 无法统计 shell 脚本中没有这样的文件或目录

mv: 无法统计 shell 脚本中没有这样的文件或目录

我编写了一个脚本将一些文件从一个文件夹移动到另一个文件夹,但出现以下错误,我检查了 2 个文件夹并注意到 1 个文件夹有此类文件,另一个文件夹没有此类文件,但为什么所有文件夹都显示“mv无法统计没有此类文件或目录”

mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/194.42.17.124_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/195.113.161.13_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/203.159.127.3_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/212.199.61.205_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/212.51.218.235_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/213.73.40.105_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/41.225.7.4_tcp.folder/data/*': No such file or directory
mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/83.230.127.122_tcp.folder/data/*': No such file or directory
[esolve@kitty tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/
[esolve@kitty tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/203.159.127.3_tcp.folder/data/
129.88.70.226   132.187.230.1    138.96.116.22   155.185.54.250   192.38.109.144  193.136.227.163  193.175.135.61  195.113.161.13  83.230.127.122
130.104.72.200  132.227.62.122   147.83.29.232   156.17.10.52     192.42.43.22    193.137.173.218  193.205.215.74  212.199.61.205
131.130.69.164  132.252.152.194  148.81.140.193  157.181.175.249  192.43.193.71   193.144.21.131   193.226.19.30   212.51.218.235
131.188.44.102  134.151.255.180  152.66.245.162  160.78.253.31    193.1.170.136   193.145.46.243   194.199.68.165  213.73.40.105
131.254.208.10  138.48.3.203     152.81.47.4     192.114.4.3      193.136.166.56  193.166.160.98   194.42.17.124   41.225.7.4

脚本是:

list=`ls dest_folder`
cd dest_folder
cwd=`pwd`
for folder in $list;do
        mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}
done

我把它跑进去了/home/esolve/project/capture/tcp_50x50/

答案1

mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}

那里的引号 ( ') 可以防止 shell 进行通配。被*逐字传递给命令,该命令失败,因为它在指示的目录中mv找不到调用的文件。*

将其更改为:

mv "${cwd}/${folder}/data"/* "${cwd}/${folder}"

(如果您的目录名称中包含空格,请使用双引号以防止出现问题。*在引号之外。)

不过,您仍然会收到空目录的错误。 (同样的原因:如果文件没有找到模式的匹配项,它将模式本身作为参数传递给命令。)

答案2

您的代码存在几个问题:

list=`ls dest_folder`

ls您将不带尾随换行符的输出存储到$list.ls输出以换行符分隔的文件名列表。newline与文件名中的任何字符一样有效,因此无法可靠地使用输出。例如,ls包含 的目录的输出ab包含名为 的文件的目录的输出相同a<newline>b

 cd dest_folder

您没有检查该命令是否失败。一般来说,您应该检查命令的退出状态,但对于 来说尤其如此cd,因为其余命令假设您位于该新目录中,而当您不在该目录中时,可能会产生严重的后果。

cwd=`pwd`

POSIX shell 已经在变量中维护了当前目录的(一个)路径$PWD,因此您不需要pwd在此处使用(特别是在一般情况下,因为命令替换会从路径中删除尾随换行符)。另外,mv接受相对路径,因此您不需要构建绝对路径。

for folder in $list;do

不加引号的变量是分割+全局shell 中的运算符。也就是说,变量的内容被拆分(在$IFS空白分隔符的特殊规则中提到的分隔符上),并且查找该拆分产生的每个元素中的通配符,以便它们可以扩展到匹配文件的列表。

在这里,您确实需要分割,但仅限于换行符,并且您不想要通配符,因此您需要禁用它:

 IFS='
 '; set -f
 for folder in $list
   mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}

同样,将变量不加引号是分割+全局操作员。在这里,您两者都不想要,因此您需要引用这些变量。

如前所述,通配符仅在未加引号时才会展开,因此您需要将其*从引号中移出。如果您之前已使用 禁用了通配符set -f,则需要set +f在调用该命令之前使用 恢复它。

更好的写法是:

cd dest_folder &&
  for folder in */;do
    mv -- "${folder}data/"* "$folder"
  done

但有一些注意事项:

  • 这将排除隐藏文件夹,并且不会从data文件夹中移动隐藏文件。
  • 我们不会检查在此过程中被覆盖的文件(您可能需要添加该-i选项mv)。
  • 通过使用*/,我们循环了目录仅,但也包括目录的符号链接。如果您不愿意,则需要[ -L "${folder%/}" ] && continue在循环内添加一个。
  • 如果其中没有非隐藏文件夹,*/则会自行扩展,因此您将收到错误消息,提示mv找不到名为*/data/*.同样,如果任何文件夹中都没有非隐藏文件,您将收到一条that-folder/data/*不存在的错误消息。

相关内容