今天在写一个shell脚本的时候遇到了一个很诡异的问题。需求很简单,在一台远程的服务器上的某个特定目录下找到最新的文件并scp到本地。一开始写的脚本大概是这样的:
#!/bin/sh
TMPDIR=xxx
SERVER=xxx
DATDIR=xxx
mkdir -p $TMPDIR
rm $TMPDIR/* -rf
FILES=`ssh $SERVER -t "ls $DATDIR -t | head -n2"`
for FILE in $FILES; do
scp $SERVER:$DATDIR$FILE $TMPDIR
done
exit 0
但是运行的时候scp命令总是不能正确执行,通过打印发现"scp $SERVER:$DATDIR$FILE $TMPDIR"这个命令莫名其妙地把$TMPDIR放到了命令的最前面并且覆盖掉了原来的scp,覆盖的长度为$TMPDIR本身的长度,于是猜想是不是$FILE本身有什么问题。把ssh $SERVER -t "ls $DATDIR -t | head -n2"返回的结果输出到文件里一看,果然如此,每个文件名的结尾处都有一个'/r'(0x0d)字符:
$xxd temp_file
0000000: 6161 7373 6574 2d32 3031 3030 3931 3930 aasset-201009190
0000010: 3232 3035 302d 7631 2e63 7376 0d 0a 6161 22050-v1.csv..aa
0000020: 7373 6574 2d32 3031 3030 3931 3930 3232 sset-20100919022
0000030: 3035 302d 7631 2e63 7376 2e73 6967 0d 0a 050-v1.csv.sig..
这样就可以解释前面的诡异问题了,scp那条命令在替换的时候会把$FILE后面的所有字符都替换到命令的最前边。最后想了一个比较土的办法,把ssh -t返回的结果用awk做一遍过滤,FILES=`ssh $SERVER -t "ls $DATDIR -t | head -n2" | awk -F"/r" '{print $1}'`,搞定:)