我正在尝试构建一个脚本,其中的一部分利用'sed‘将文件名标记到该文件中每行的末尾,然后将输出转储到主列表中。脚本中给我带来麻烦的部分如下:
DIR=/var/www/flatuser
FILES=$DIR/*
for f in $FILES
do
echo "processing $f file...."
sed -i "s/$/:$f/" $f
cat $f >> $DIR/master.txt
done
问题是'sed‘语句在for循环之外工作得很好,但是当我把它放到脚本中时,我相信它在解释美元符号时遇到了问题。我尝试了几乎所有我能想到的“和”的组合,让它解释变量,它不断地要么在每一行的末尾放上"$f“,要么直接失败。
感谢您的任何意见!
发布于 2013-03-22 16:11:54
就我个人而言,我会这样做:
dir=/var/www/flatuser
for f in "$dir"/*; do
[[ $f = */master.txt ]] && continue
while read -r; do printf '%s:%s\n' "$REPLY" "${f##*/}"; done <"$f"
done >/var/www/flatuser/master.txt
它不会像sed -i
那样就地修改文件,因此可以安全地多次运行( sed -i
版本会在每次运行时就地将文件名添加到文件中,所以最终每行都会有多个文件名的副本)。
而且,sed -i
不是由POSIX指定的,所以并不是所有的操作系统都有它。
发布于 2013-03-22 16:00:11
你只需要避开美元符号:
sed -i "s/\$/:$f/" "$f"
这样外壳就会把它直接传递给sed
。
为了扩展Charles Duffy关于引用变量的观点:
DIR=/var/www/flatuser
for f in "$DIR"/*
do
echo "processing $f file...."
sed -i "s/\$/:${f##*/}/" "$f"
cat "$f" >> "$DIR/master.txt"
done
如果任何文件名包含空格,那么如果将文件名列表分配给$FILES
,就会为时已晚;您无法再区分属于文件名的空格和分隔文件名的空格。您也可以使用数组,但将glob直接放在for循环中会更简单。下面是使用数组的方法:
DIR=/var/www/flatuser
FILES=( "$DIR"/* )
for f in "${FILES[@]}"
do
echo "processing $f file...."
sed -i "s/\$/:${f##*/}/" "$f"
cat "$f" >> "$DIR/master.txt"
done
对于不使用-i
的sed
版本,这里有一个显式处理模拟就地编辑所需的临时文件的方法:
t=$(mktmp sXXXX); sed "s/\$/:$f/" "$f" > "$t"; mv "$t" "$f" && rm "$t"
发布于 2013-03-22 16:24:08
问题不在于美元符号。这是因为变量$f包含一个"/“字符,sed使用这个字符来分隔表达式。尝试使用"@“作为分隔符。
DIR=/var/www/flatuser
FILES=$DIR/*
for f in $FILES
do
echo "processing $f file...."
sed -i s@"$"@:"$f"@ $f
cat $f >> $DIR/master.txt
done
https://stackoverflow.com/questions/15574641
复制