【问题标题】:Bash beginner: Error when tries to copy directory itself when making subdirectoriesBash初学者:在创建子目录时尝试复制目录本身时出错
【发布时间】:2012-05-23 03:51:13
【问题描述】:
  • 我有一个目录,里面有 4 个目录。
  • 我要创建第 5 个目录 (cx1_date) 并创建 4 个与原始目录同名的空目录
  • 然后我想将每个原始目录中的两个文件复制到具有各自名称的新子目录中
  • 我认为我遇到了一个错误,因为它试图复制 PWD 本身(因为这显示为 find 调用的结果),所以我尝试包含一个 if 语句,但我认为它不起作用

    now=$(date +"%m_%d_%Y")
    
    PWD="/nmr/charlie"
    
    mkdir $PWD/cx1_$now
    
    for name in $(find $PWD -maxdepth 1 -type d); do
    if [[ "$name" = "$PWD" && "$PWD" = "$name" ]];
    then 
        :
    else 
        cd $PWD/cx1_$now
        mkdir $PWD/$name
        cd $PWD/$name 
        cp file1.ext $PWD/cx1_$now/$name
        cp file2.ext $PWD/cx1_$now/$name
    fi 
    done
    

错误的第一行

mkdir: 无法创建目录`/nmr/charlie/cx1_05_15_2012//nmr/charlie/cx1_05_15_2012': 没有这样的文件或目录

提前感谢您提供的任何帮助!

查理

【问题讨论】:

  • 在问题中包含错误
  • 您可以通过在脚本顶部附近插入set -vx 来调试您的shell 脚本。 (下面的答案旨在解决问题)。祝你好运。

标签: bash subdirectory copying


【解决方案1】:

您正在使用 $PWD,就好像它同时表示“/nmr/charlie”和“/nmr/charlie/cx1_date”一样。它只表示第一个。

此外,当您遍历 $PWD 中的文件夹时,它也会包含 cx1_date,因为您已经创建了它,所以您应该检查一下。

而且我不建议使用 PWD 作为变量名,因为它可以用于其他用途。

[EDIT] 另外,$name 获取目录的完整路径,因此您需要使用 basename 仅获取目录的名称而不获取完整路径。另外,我在 if 行中犯了一个错误,它的意思是 != 而不是 = 在第二次比较中。对不起,我当时没有外壳来测试。下面的代码现在可以工作了,我已经测试过了。

这应该可行:

now=$(date +"%m_%d_%Y")

DIR="/nmr/charlie"

mkdir $DIR/cx1_$now

for name in $(find $DIR -maxdepth 1 -type d)
do
    if [[ "$name" != "$DIR" && "$name" != "$DIR/cx1_$now" ]];
    then 
        targetdir=$(basename $name)
        cd $DIR/cx1_$now
        mkdir $DIR/cx1_$now/$targetdir
        cd $DIR/$targetdir
        cp file1.ext $DIR/cx1_$now/$targetdir
        cp file2.ext $DIR/cx1_$now/$targetdir
    fi 
done

【讨论】:

  • 我收到以下错误?我仍然无法弄清楚为什么它会翻倍。 /home/charlie/Desktop/scripts/test.sh:第 17 行:cd:/nmr/charlie//nmr/charlie/cx1_2012_05_15:没有这样的文件或目录
【解决方案2】:

第二个mkdir 不想要$PWD

now=$(date +"%m_%d_%Y")

DIR="/nmr/charlie"

mkdir $DIR/cx1_$now

for name in $(find $DIR -maxdepth 1 -type d)
do
    if [[ "$name" != "$DIR" ]]
    then 
        (cd $DIR/cx1_$now; mkdir $name)
        (cd $DIR/$name 
         cp file1.ext $DIR/cx1_$now/$name
         cp file2.ext $DIR/cx1_$now/$name
        )
    fi
done

另外,PWD 是一个内置变量;您不应该设置它(通过cd 命令除外)。

if 中不需要对称测试;您可以使用!= 而不是= 来避免空的then 子句(好的,它包含一个很好的止痛药: 命令;如果您反转测试,则不需要它)。

我通常把cd操作放到子shell中;这样,我就不会那么困惑了。第二个mkdir 行的替代方法是这样,它不需要cd 或子shell:

mkdir -p $DIR/cx1_$now/$name

我建议对日期使用 ISO 8601 格式,例如:

now=$(date +"%Y_%m_%d")

这样,目录将自动按日期顺序排序。


我仍然收到错误:

mkdir: cannot create directory `/nmr/charlie/directory_name_1': File exists
/home/charlie/Desktop/scripts/test.sh: line 16: cd: /nmr/charlie//nmr/charlie/directory_name_1: No such file or directory 

问题可能意味着我们尚未正确过滤。例如,每次创建备份目录时,都会将之前的备份目录全部备份到新的目录中,这就有点过分了。所以,练习的另一部分是更好地过滤find 的输出。

...我们应该使用目录的基本名称,我们也可以避免所有cd 操作:

now=$(date +"%m_%d_%Y")

DIR="/nmr/charlie"

mkdir $DIR/cx1_$now

for name in $(find $DIR -maxdepth 1 -type d | grep -v '/cx1_[^/]*$')
do
    if [[ "$name" != "$DIR" ]]
    then
        targetdir=$DIR/cx1_$now/$(basename $name)
        mkdir -p $targetdir
        cp $name/file1.ext $name/file2.ext $targetdir
    fi
done

您确实知道使用“sh -x script.sh”或“bash -x script.sh”来运行脚本并查看它在做什么。我什至不确定我们是否需要 if 条件和 grep 从列表中过滤掉任何看起来像备份目录的内容。

我注意到,这仅在目录路径健全且不包含空格的情况下才有效。如果您使用不可移植的文件名(可移植的文件名仅使用[-_.A-Za-z0-9]),事情就会很快出错。换行符和空格真的很乱。

请注意,如果您在/nmr/backup/charlie 下的目录或/nmr/charlie 本身以外的任何位置进行备份,这会更简单。但是,小心,可以根据要求在原地完成。

【讨论】:

  • 感谢您的帮助,有用的提示,但我仍然收到错误:mkdir: cannot create directory `/nmr/charlie/directory_name_1': File exists /home/charlie/Desktop/scripts/test. sh:第 16 行:cd:/nmr/charlie//nmr/charlie/directory_name_1:没有这样的文件或目录
  • 很酷,所以我现在使用 bash -x 来查看它在做什么,我认为它在没有实际实现脚本的情况下进行了故障排除,但我只是通过使用它覆盖了很多数据!就我而言,那里有点错误。无论如何你可以保守地做到这一点,这样你就可以在没有实际采取所有 cp rm 动作等的情况下看到它在做什么?
  • 有一些技巧。当您获得正确的语法时,sh -nv script 可以提供帮助。 -n 表示“不执行”,-v 表示“详细”。一旦您开始测试,请确保您在真实数据的副本上进行测试,直到您确定它的行为正常为止。如果您的脚本可能造成损坏(通过删除文件或不可逆转地更改它们),这一点就显得尤为重要。我要做的另一件事是将echo 放在任何危险命令的前面,直到我很高兴它们是正确的;这向我展示了(或多或少)在没有实际执行的情况下会执行什么。否则,请保持良好的备份!
猜你喜欢
  • 2022-06-13
  • 1970-01-01
  • 1970-01-01
  • 2015-10-15
  • 2014-11-22
  • 2019-01-14
  • 2016-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多