如何在bash中处理带有美元字符($)的文件名?

时间:2010-10-29 08:42:48

标签: bash

我设法凑齐了以下脚本,将文件从一个Samba共享移动到另一个。它似乎适用于所有合法的Windows文件名,除非文件名中有美元字符($)。它失败的典型文件名是:〜$ file.doc

任何帮助都将不胜感激。

#!/bin/bash
# Script to move old files from public to quarantine

 srcbase=/net/public
 destbase=/net/quarantine
 logfile=$srcbase/moved.log
 date > $logfile 2>1&
 find $srcbase -noleaf -atime +30 -print0 | while IFS="" read -r -d "" file ; do
   if [ -f "$file" ]; then
     relname="${file#*$srcbase}"
     destname="$destbase$relname"
     destdir="$(dirname "$destname")"
     if [ ! -d "$destdir" ]; then
       cmd1="mkdir -p \""$destdir"\""
       eval "$cmd1"  >> $logfile 2>&1
     fi
     cmd="mv --backup=t -v \""$file"\" \""$destname"\""
     eval "$cmd" >> $logfile 2>&1
     if [ -e "$destname" ]; then
       cmd2="touch -a \""$destname"\""
       eval "$cmd2" >> $logfile 2>&1
     fi
   fi
 done
 date >> $logfile 2>1&
 echo Deleting empty directories from "$srcbase" >> $logfile 2>&1
 find "$srcbase" -type d -empty -delete >> $logfile 2>&1

3 个答案:

答案 0 :(得分:3)

你当然是。您正在使用eval

BASH FAQ entry #50

答案 1 :(得分:3)

问题可能来自于在一个被证实的变量中使用文件名。

如果你在eval的设置中使用单引号,它可以防止在那里解释$。:

cmd2="touch -a '$destname'"

创建cmd时仍会替换$destname

但是我强烈建议您不要在文件系统上找到的文件名中构建eval。这是一个巨大的后门。例如:如果某个恶作剧者在源文件系统上创建文件名; rm -rf /该怎么办?

Explanation of the security issues with eval

答案 2 :(得分:3)

您的问题是您使用eval。我建议反对它,因为它非常非常非常必要且非常难以使用。在你的情况下,我认为不需要它

如果用此

替换循环内容
   if [ -f "$file" ]; then
     relname="${file#*$srcbase}"
     destname="$destbase$relname"
     destdir="$(dirname "$destname")"
     if [ ! -d "$destdir" ]; then
        mkdir -p "$destdir" >> $logfile 2>&1
     fi
     mv --backup=t -v "$file" "$destname"
     if [ -e "$destname" ]; then
        touch -a "$destname" >> $logfile 2>&1
     fi
   fi

即使文件名中包含$,它也应该可以正常工作。

您是否发现情况并非如此?