我有一个包含.txt.xy
文件的目录$dir
和包含.txt.xy
文件的子目录。我尝试迭代每个文件,并将整个路径以及没有$dir
作为参数的路径传递给这样的程序:
dir="/path/to/"
suffix=".xy"
find "$dir" -name "*.txt.xy" -print0 | xargs -0 -I {} sh -c 'program "$1" |
subprogram filename="$2"' _ {} "$(echo {} | sed -e "s#^${dir}##" -e "s#${suffix}$##")"
$1
应为完整路径(例如/path/to/subdir/file.txt.xy
)$2
应该是没有$dir
和$suffix
的完整路径(例如subdir/file.txt
)
$1
是proper完整路径,但$2
也是完整路径,就好像$(...)
中的管道从未执行一样。我在这里错过了什么?
您的尝试似乎相当迂回。听起来你在找
find /path/to -name "*.txt.xy" -exec sh -c '
for f; do
g=${f##*/}
program "$f" | subprogram filename="${g%.xy}"
done' _ {} +
如果你真的需要你的参数在变量中,可以把后缀作为$0
传递,这在这里没有任何用处。它有点晦涩,但有助于避免双引号带来的混乱。
find /path/to -name "*.txt.xy" -exec sh -c '
for f; do
g=${f##*/}
program "$f" | subprogram filename="${g%"$0"}"
done' ".xy" {} +
上面的内容只是将g
修剪为基本名称,我想仔细阅读后您不会想要这个名称。因此,在$0
中传递/path/to
,并在中硬编码.xy
find /path/to -name "*.txt.xy" -exec sh -c '
for f; do
g=${f#"$0"/}
program "$f" | subprogram filename="${g%.xy}"
done' "/path/to" {} +
或者如果你真的需要两者都是命令行参数,
dir="/path/to"
suffix=".xy"
find "$dir" -name "*.txt$suffix" -exec sh -c '
suffix=$1
shift
for f; do
g=${f#"$0"/}
program "$f" | subprogram filename="${g%"$suffix"}"
done' "$dir" "$suffix" {} +
失败的一个原因是,使用双引号下的xargs
的命令替换甚至在执行前者之前就被shell扩展了。避免这种情况的一种方法是在sh -c
创建的子外壳内进行整个替换,作为
find "$dir" -name "*.txt.xy" -print0 |
xargs -0 -I {} sh -c '
f="{}"
g="$(echo "$f" | sed -e 's|"'^"${dir}"'"||' -e 's|"'\"${suffix}"$'"||' )"
program "$f" | subprogram filename="$g"
'