开发者

How to handle filenames with dollar character ($) in bash?

I have managed to cobble together the following script that moves files from one Samba share to another. It seems to work for all legal windows filenames except when there is a dollar character ($) in the filename. Typical filename it fails on is: ~$file.doc

Any help would be appreciated.

#!/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&g开发者_如何学Got;&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


Of course you are. You're using eval.

BASH FAQ entry #50


The problem probably comes from using the filenames in a variable that is evaled.

If you would use single quotes in the setup of the eval it prevents that the $ is interpreted there e.g.:

cmd2="touch -a '$destname'"

The $destname is still replaced when cmd is created.

BUT: I'll advise strongly against building evals from filenames you find on a filesystem. This is a huge backdoor. e.g.: what if some prankster creates a file name ; rm -rf / on the source filesystem?

Explanation of the security issues with eval


Your problem is your use of eval. I recommend against it since it's very, very rarely necessary and extremely difficult to use. I don't see any need for it in your case

If you replace the contents of your loop with this

   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

It should work just as well, even with $ in the file name.

Did you find that this was not the case?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜