Bash循环涉及将文件名附加到单词
Posted
技术标签:
【中文标题】Bash循环涉及将文件名附加到单词【英文标题】:Bash loop inolving appending file names to a word 【发布时间】:2015-05-12 14:06:10 【问题描述】:我有三个可以工作的命令,我想创建一个循环来执行所有文件,而不是必须按名称单独为所有文件键入它们。我不明白为什么它不能作为循环工作。
我想要它做的,是把“索引”这个词放在左上角,然后 之后的每一行,从 1 到我的 .gcount 文件中的行数的数字; 然后将上面的内容粘贴到它的右侧,将我的每个 .gcount 文件的内容粘贴到名为“index_foo.gcount”的新文件中
根据错误消息(目录不存在),问题似乎是大括号使用不正确?
for files in ./*.gcount
do
echo "Index" > index
seq 1 1 $(cat $files | wc -l) >> index
paste -d "\t" index $files > index_$files
done
【问题讨论】:
那是因为index_$files
将扩展为 index_./stuff.gcount
并且由于目录 index_.
不存在,Bash 抱怨。解决此问题的两种可能性:1) 使用for files in *.gcount
,这样files
中就没有任何斜线。 2) 只保留文件中的基本名称,紧跟在do
关键字之后:files=$files#./
。这将摆脱领先的./
。
【参考方案1】:
更新:问题是$files
将包含目录名称,当您尝试从中创建输出文件名时会导致问题。我最初认为这可能是文件名中的空格问题(仅使用 in *
测试过),但 gniourf_gniourf 发现了真正的问题:
这是因为
index_$files
将扩展为index_./stuff.gcount
并且由于目录index_.
不存在,Bash 抱怨。解决此问题的两种可能性:1) 使用for files in *.gcount
,这样文件中就没有任何斜线。 2) 只保留文件中的基本名称,紧跟在do
关键字之后:files=$files#./
。这将摆脱领先的./
。
(编辑以使帖子包含真正的解决方案。代表应该去 gniourf_gniourf,但我们进行了讨论,他可以编辑而不是发布他的答案。)
这是原始帖子,它可能仍然展示了一些好的做法:
在这里可以工作,但有一个错误是“索引”行也会被编号。
检查您的任何文件名是否包含空格,因为这会破坏它。要使脚本正确处理此类文件名,您应该引用 $files
以确保它扩展为单个单词,例如
paste -d "\t" index "$files" > index_"$files"
,其他行也类似。 (顺便说一句,那里不需要,尽管它们不会造成伤害。)
如果您只想在文件中添加行号,使用nl(1)
会更容易(这似乎是 POSIX,所以它应该是相当可移植的)。这是一个您可以使用的示例,它与您所追求的格式相匹配:
echo Index; nl -nln -ba "$files"; > index_"$files"
括号让您可以将多个命令的输出重定向到同一个位置。
另一件(有点挑剔的)值得注意的事情是,您可以使用--
和许多命令来关闭标志处理,这使您可以处理以-
开头的文件名。这是一个示例:ls -- -weirdly_named_file
。
您可以通过以下方式修复原始版本中的编号错误:
seq 1 1 $(wc -l < "$files") > index
echo "Index"; paste -d "\t" index "$files"; > index_"$files"
This question 包含用于在文件开头添加一行的其他变体。
【讨论】:
echo "Index"; cat index_"$files"; > index_"$files"
不起作用:重定向 > index_"$files"
将首先截断文件,然后运行组并将其输出重定向到 index_"$files"
... 所以你只会得到 Index
in那个文件。您想要的是 echo "Index"
就在组中的 paste
之前。
@gniourf_gniourf:谢谢!这很尴尬。另一个问题是 wc -l "$files"
在其输出中包含文件名。以上是关于Bash循环涉及将文件名附加到单词的主要内容,如果未能解决你的问题,请参考以下文章