说,文件'listall'包含目录列表,我想列出这些目录中的所有文件,包括目录路径。 我在下面写了一个bash脚本。
#!/bin/bash
\rm listZ
echo ' ' > listZ
for i in `cat listall`; ls $i | sed -e '1,$s/^/$i\//g' >> listZ; done
但是在sed命令中,$ i不会被目录名替换 我尝试使用双引号进行sed命令,但无济于事。这是在cygwin。 我该怎么办?
答案 0 :(得分:1)
单引号字符串不受变量替换的影响。但是,将变量移动到外部单引号字符串是一件简单的事情,例如:
pax> one=1 ; echo '
...> 1
...> 101
...> 3.14159' | sed 's/'$one'/x/g'
x
x0x
3.x4x59
在你的情况下,它将是:
for i in `cat listall`; do ls $i | sed -e '1,$s/^/'$i'\//g' >> listZ; done
# ^^^^
请注意,根据您的评论之一,如果您的文件中包含sed
特有的字符,则会让您感到悲伤。例如,如果它们包含/
个字符,则您需要阻止它被sed
s
命令解释。
也许最简单的方法是使用另一个不可能位于输入文件中的分隔符:
for i in `cat listall`; do ls $i | sed -e '1,$s?^?'$i'/?g' ; done
答案 1 :(得分:1)
DontParseLs和DontReadLinesWithFor。
你要问的问题可以通过使用双引号而不是单引号来修复,但是,你需要转义任何你不打算让shell解释的shell元字符(换句话说,你' d必须反斜杠 - 转义地址范围1,$
中的美元符号,或使用双引号旁边的单引号,并可能更改为不同的分隔符以处理变量值$i
中的斜杠; '1,$'"s:^:$i:"
)。
但是你的整个任务可以作为一个命令执行。
IFS=$'\n' find $(cat listall) -mindepth 1 -maxdepth 2 -print >listZ
IFS
仅在listall
包含带有空格的文件名时才是必需的。while read -r directory; do
printf '%s\n' "$directory"/* "$directory"/*/*
done <listall >listZ
您仍然原则上需要转义任何其他shell元字符(星号,方括号,问号)。
listall
(我最初误解了你的问题,假设sed "s:^:$i/:" listall >listZ
包含文件名,而不是目录名。我在下面保留原来的答案。)
'1i\ '
如果您实际上需要第一行上的空白区域(可能会将sed
添加到1,$
脚本中)。地址范围sed
是/g
中的默认值,因此指定它是多余的。因为每行只能有一个替换,$i
标志也是冗余的(这意味着,在一行上替换所有出现,而不是仅替换第一行)。如果{{1}}中有冒号,请使用不同的分隔符。
答案 2 :(得分:0)
正如paxdiablo所说(感谢tripleee),我的问题是shell变量包含几个&#39; /&#39;字符,搞乱了sed substitute命令。所以我们可以使用另一个分隔符来避免这个问题,例如&#39 ;;&#39;而不是&#39; /&#39;对于sed。 所以正确的方法是
#!/bin/bash
\rm listZ
echo ' ' > listZ
for i in `cat listall`; ls $i | sed 's;^;$i' >> listZ; done
注意,在我的情况下,文件listall看起来像
/usr/bin/
/usr/local/bin/