Linux bash-排除“中的目录”;对于美元格式的文件(查找…);

Linux bash-排除“中的目录”;对于美元格式的文件(查找…);,linux,bash,for-loop,find,backup,Linux,Bash,For Loop,Find,Backup,我必须执行一个脚本,它将所有*.txt文件从主目录复制到这个脚本(${1})的第一个参数中指定的新创建的目录 如果备份目录已经存在,我想跳过它。我试着在find中使用-prune,但它对我不起作用。最后,我在循环中做了if语句,这也不起作用,我不知道为什么…谢谢大家的帮助 这是我的密码: #!/bin/bash mkdir ${1} for file in $(find ~/ -name *.txt) do if [ ! -f ~/${1}/$file ] then

我必须执行一个脚本,它将所有*.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

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

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

您可以将此简化为

mkdir -p "$1"
find ~/ -name "$1" -prune , -name '*.txt' -print0 | xargs -0 cp -n -v -t "$1"
您必须引用
*.txt
,否则shell会将其扩展到当前目录中的所有
.txt
文件,而不是搜索主目录下的所有
.txt
文件<代码>-名称“$1”-删除不包括备份目录

使用尽可能多的文件名进行调用,从而节省大量时间

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

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

这应该可以:

#!/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" -- {} \; \)
赞成:使用名称中有空格或有趣符号的文件(与您的不同)(除了一个愚蠢的案例,请参见下面的Con)

缺点:正如Ormaj在一篇评论中指出的,如果目标路径的名称包含模式字符
*
,则此操作可能会失败。这种情况会被安全地考虑在内,如果发生这种情况,脚本会优雅地退出

解释。

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

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

“对我来说不起作用”。。。嗯,好的。如何实现?如果不需要目录递归,
cp*.txt destination/
,可以使用
cp-n
。另请参见
rsync
。文件名中有空格时立即中断。另外,绝对/相对路径有点笨拙。感谢回复,但cp仍在尝试将文件从$dest path复制到$dest path…当destdir包含模式字符时,这是不安全的。通常,
-path
-prune
不会混合使用。与globs不同,
-path
不会单独计算每个路径组件。e、 g.
/foo/*/bork
匹配
/foo/bar/bork
/foo/bar/baz/bork
@ormaj你说得对!我忘记了愚蠢的模式字符
*
。现在你为什么说
-path
-prune
不要混在一起?在
manfind
中有一个很好的例子说明了如何将它们一起使用。对了,我把它误读为“使用-name而不是-path”。不过这很接近。