bash - 排除“for file in $(find ...)”中的目录

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14034190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 04:05:08  来源:igfitidea点击:

bash - excluding directory in "for file in $(find ...)"

linuxbashfor-loopfindbackup

提问by jirinovo

I have to do a script, which copy all the *.txt files from home directory to the newly created directory specified in the first argument of this script (${1}).

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

If the backup directory already exists, I want to skip it. I was trying the -prune excluding in find, but it doesn't work for me. Finally I have made if statement in the loop, which also doesn't work, and I don't know why...Thank's for help!!

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

Here's my code:

这是我的代码:

#!/bin/bash

mkdir 

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

do

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

done

采纳答案by perreal

You have an error in the code, You are creating the directory:

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

mkdir 

But copying and testing a different path (-f ~/${1}/$file, -t ~/${1}). Create a variable to prevent such errors:

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

#!/bin/bash
dest=~/
[ -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

回答by gniourf_gniourf

This should do:

这应该做:

#!/bin/bash

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

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

[[ "$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: Works with files that have spaces or funny symbols in their name (unlike yours) (except one stupid case, see Conbelow).

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

Con: As ormaaj pointed out in a comment, this might fail miserably if the name of your destination path contains the pattern character *. This case is safely taken into account, and the script exits gracefully if it ever happens.

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

Explanations.

说明。

  • Give an argument to that script. It can be absolute of relative to the current directory. readlink, with the -moption will take care to translate this to an absolute path: that's the variable destdir.
  • The directory $destdiris created with its parents, if applicable.
  • In home directory, if we find $destdirdirectory, we prune this branch, otherwise, we look for all *.txtfiles and copy them to $destdir.
  • 为该脚本提供一个参数。它可以是相对于当前目录的绝对值。readlink, 使用该-m选项将注意将其转换为绝对路径:即变量destdir
  • $destdir如果适用,该目录与其父目录一起创建。
  • 在主目录中,如果找到$destdir目录,则修剪此分支,否则,我们查找所有*.txt文件并将它们复制到$destdir.

Once again, this script is 100% safe regarding file names with funny symbols: spaces, newline characters or hyphens, except for the pattern character *in the destination directory name, but that case is handled safely by a graceful exit, instead of potentially screwing up the files.

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

回答by Olaf Dietsche

You can simplify this to

您可以将其简化为

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

You must quote *.txt, otherwise the shell will expand it to all .txtfiles in the current directory instead of searching for all .txtfiles below your home directory. -name "$1" -pruneexcludes the backup directory.

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

xargscalls cpwith as many filenames as possible and so saves a lot of time.

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

cp -ninstead of cp -iprevents overwriting files, which already exist. If you want to keep it, you might replace -nby -iof course.

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

If you want to retain the directory hierarchy, rsyncmight be better suited for this backup task.

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