Bash初学者:在制作子目录时尝试复制目录本身时出错

时间:2012-05-15 15:31:27

标签: bash subdirectory copying

  • 我有一个包含4个目录的目录。
  • 我想创建第5个目录(cx1_date)并创建4个与原始目录名称相同的空目录
  • 然后,我想将每个原始目录中的两个文件复制到具有各自名称的新子目录
  • 我认为我收到错误是因为它试图复制PWD本身(因为这显示为查找调用的结果),所以我试图包含一个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':没有这样的文件或目录

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

查理

2 个答案:

答案 0 :(得分: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子句(好的,它包含一个很好的anodyne :命令;如果你反转它,你不需要它检验)。

我通常将cd次操作放入子壳中;这样,我就不那么困惑了。第二个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以外的任何位置进行备份,则会更简单。但是,小心,可以按要求就地进行。

答案 1 :(得分:2)

您正在使用$ PWD,就好像它意味着“/ nmr / charlie”和“/ nmr / charlie / cx1_date”。它只意味着第一个。

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

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

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

这应该有效:

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