0

我需要创建目录树的克隆,以便清理重复文件。

我不需要文件的副本,我只需要文件,所以我想创建一个带有硬链接的匹配树。

当我意识到我的备份需要几个小时时,我在几分钟内把它放在一起

它只是回显我重定向到文件以在运行之前检查的命令。

当然,通常的问题,例如包含引号或逗号的文件和目录尚未得到解决(bash 脚本很糟糕,不是吗,这个和包含前导破折号的文件)

是不是有一些实用程序已经以强大的方式做到了这一点?

BASEDIR=$1
DESTDIR=$2
for DIR in `find "$BASEDIR" -type d` 
do
   RELPATH=`echo $DIR | sed "s,$BASEDIR,,"`
   DESTPATH=${DESTDIR}/$RELPATH
   echo mkdir -p \"$DESTPATH\"
done

for FILE in `find "$BASEDIR" -type f` 
do
   RELPATH=`echo $FILE | sed "s,$BASEDIR,,"`
   DESTPATH=${DESTDIR}/$RELPATH
   echo ln \"$FILE\" \"$DESTPATH\"
done
4

1 回答 1

1

通常使用这样的 find 是一个坏主意 - 您基本上依赖于在空格上分隔文件名,而实际上所有形式的空格在大多数 UNIX 系统上都可以作为文件名有效。Find 本身能够对找到的每个文件运行单个命令,这通常是一个更好的使用方法。我会建议做这样的事情(为了简单起见,我会使用几个脚本,但不确定将这一切合二为一有多容易):

主.sh:

BASEDIR="$1" #I tend to quote all variables - good habit to avoid problems with spaces, etc.
DESTDIR="$2"
find "$BASEDIR" -type d -exec ./handle_file.sh \{\} "$BASEDIR" "$DESTDIR" \; # \{\} is replaced with the filename, \; tells find the command is over
find "$BASEDIR" -type f -exec ./handle_file.sh \{\} "$BASEDIR" "$DESTDIR" \;

句柄文件.sh:

FILENAME="$1"
BASEDIR="$2"
DESTDIR="$3"
RELPATH="${FILENAME#"$BASEDIR"}" # bash string substitution double quoting, to stop BASEDIR being interpreted as a pattern
DESTPATH="${DESTDIR}/$RELPATH"
if [ -f "$FILENAME" ]; then
  echo ln \""$FILENAME"\" \""$DESTPATH"\"
elif [ -d "$FILENAME" ]; then
  echo mkdir -p \""$DESTPATH"\"
fi

我已经用一个带有空格、星号、撇号甚至文件名中的回车的简单树对此进行了测试,它似乎可以工作。

显然删除转义的引号和“回声”(但留下真实的引号)以使其真正起作用。

于 2014-09-27T16:05:48.980 回答