4

我必须编写一个脚本,将所有 *.txt 文件从主目录复制到该脚本的第一个参数 (${1}) 中指定的新创建目录。

如果备份目录已经存在,我想跳过它。我正在尝试在 find 中排除 -prune ,但它对我不起作用。最后我在循环中做了if语句,这也不起作用,我不知道为什么......谢谢帮助!

这是我的代码:

#!/bin/bash

mkdir ${1}

for file in $(find ~/ -name *.txt)

do

    if [ ! -f ~/${1}/$file ]
    then
        cp -i -v $file -t ~/${1}
    fi

done
4

3 回答 3

1

这应该这样做:

#!/bin/bash

[[ -n "$1" ]] || { echo >&2 'Give me an argument!'; exit 1; }

destdir=$(readlink -m -- "$1")

[[ "$destdir" == *\** ]] && { echo >&2 "Sorry, I'm in the stupid situation where the destination dir contains the \`*' character. I can't handle this."; exit 1; }

mkdir -pv -- "$destdir" || { echo >&2 "Couldn't create directory \`$destdir'. Sorry."; exit 1; }

find "$HOME" -path "$destdir" -prune -o \( -name '*.txt' -exec cp -iv -t "$destdir" -- {} \; \)

Pro:适用于名称中包含空格或有趣符号的文件(与您的不同)(除了一种愚蠢的情况,请参见下面的Con)。

缺点:正如 ormaaj 在评论中指出的那样,如果目标路径的名称包含模式字符,这可能会失败*。安全地考虑了这种情况,如果发生这种情况,脚本会优雅地退出。

解释。

  • 给那个脚本一个参数。它可以是相对于当前目录的绝对值。readlink, 使用该-m选项会注意将其转换为绝对路径:这就是变量destdir.
  • 如果适用,该目录$destdir与其父目录一起创建。
  • 在主目录中,如果我们找到$destdir目录,我们会修剪这个分支,否则,我们会查找所有*.txt文件并将它们复制到$destdir.

再一次,这个脚本对于带有有趣符号的文件名是 100% 安全的:空格、换行符或连字符,除了*目标目录名称中的模式字符,但这种情况可以通过优雅的退出安全地处理,而不是潜在地搞砸文件。

于 2012-12-25T22:30:10.603 回答
0

您可以将其简化为

mkdir -p "$1"
find ~/ -name "$1" -prune , -name '*.txt' -print0 | xargs -0 cp -n -v -t "$1"

您必须引用*.txt,否则 shell 会将其扩展到.txt当前目录中的所有文件,而不是搜索.txt您的主目录下的所有文件。-name "$1" -prune不包括备份目录。

xargs调用cp尽可能多的文件名,从而节省大量时间。

cp -n而不是cp -i防止覆盖已经存在的文件。如果你想保留它,你当然可以-n替换-i

如果您想保留目录层次结构,rsync可能更适合此备份任务。

于 2012-12-25T22:00:43.200 回答
0

您的代码中有错误,您正在创建目录:

mkdir ${1}

但是复制和测试不同的路径(-f ~/${1}/$file-t ~/${1})。创建一个变量以防止此类错误:

#!/bin/bash
dest=~/${1}
[ -d "$dest" ] || mkdir "$dest"
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for file in $(find ~/ -name '*.txt' -print)
do
  dfile="$dest/"$(basename "$file")
  if [ "$file" -ef "$dfile" ]; then
    echo same
  else
    cp -i -v "$file" -t "$dfile"
  fi  
done
IFS=$SAVEIFS
于 2012-12-25T21:47:01.920 回答