如何在没有输入文件的情况下将参数传递给sed。 sed用单引号引起来,并且已经在其中加了管道。
git filter-branch -f --index-filter \
'git ls-files -s | sed -i "s-\t\"*-&dirname/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
如果目录名是硬编码的,则上面的代码可以正常工作。但是我需要将目录名从命令行参数传递给脚本。我正在尝试以下方法,但没有运气。
'set subdir=$folder;git ls-files -s | sed -i "s-\t\"*-&$subdir/-" |
sed说输入文件丢失。我不能直接将输入文件传递给sed。我看到如下错误。
Rewrite 9c86de42b7f3228e3d45a278c8caf7e24c8e55cf (1/2) (0 seconds passed, remaining 0 predicted)
sed: no input files
答案 0 :(得分:2)
您正在使用sed -i
,它会在适当位置编辑其命令行参数(即文件名)。但是,您正在从标准输入中读取内容,并且未提供任何命令行参数。如果您只想过滤标准输入,请从-i
命令中省略sed
。
答案 1 :(得分:2)
您在这里有两个选择。您可以评估$subdir
来构建固定的sed
命令,然后将其设置为过滤器;或者您可以在git filter-branch
将调用的shell片段中求值。
要理解后者,请意识到您的--index-filter
字符串变为an ordinary shell variable:
--index-filter)
filter_index="$OPTARG"
;;
然后是passed to eval
:
eval "$filter_index" < /dev/null ||
die "index filter failed: $filter_index"
eval
表示$filter_index
中的表达式是通过--index-filter
参数设置的,可以访问the filter-branch script中的所有shell变量和函数。不幸的是,它的 private 变量都不包含您想要的表达式,但是您可以访问其 environment 变量,这意味着您可以将值放入环境变量中。换句话说,您可以将subdir=<whatever>
作为环境提供给原始表达式。
无论如何,作为bk2204 answered,您需要删除-i
选项。除此之外,sed
的某些版本不接受\t
作为制表符(大概是您的,请注意这一点)。
要更早地扩展变量,只需执行此操作。例如:
... --index-filter \
'git ls-files -s | sed "s-\t\"*-&'$folder'/-" | ...
(我自己在这里删除了-i
)。请注意,这如何退出单引号,展开$folder
,然后重新输入单引号。如果$folder
可能包含空格,请确保在此处展开时使用双引号:
... --index-filter \
'git ls-files -s | sed "s-\t\"*-&'"$folder"'/-" | ...
这里引号的嵌套非常棘手:单引号内的内容都是一个大字符串,作为在$filter_index
脚本中设置变量filter-branch
的参数提供。 eval
通过第二次评估运行它,分解为管道(git ls-files
,通过管道传输到sed
,通过管道传输到git update-index
),并运行各种多个命令,所有这些对象的标准输入都重定向到/dev/null
。