我有一个文件夹 x,其中包含许多子文件夹 ale、bae、galo,每个子文件夹内都有一个 .pest 文件。
x/ale/ale.pest
x/bae/bae.pest
x/galo/galo.pest
我在文件夹 y 中有一个列表,其中包含我应该 cat .pest 文件的顺序
bae
galo
ale
从我的 x 文件夹中我正在尝试
for file in ./*/*.pest; do while read line; do cat "$line".pest; done; done <./y/list
但它不起作用。
答案1
您在列表中有顺序,因此不要将文件名与文件名通配模式匹配。相反,从列表中读取的字符串构造名称:
#!/bin/sh
while read -r name; do
cat "x/$name/$name.pest"
done <y/list >concatenated.pest
这将连接所有相关.pest
文件并在当前目录中创建一个从这些文件调用的单个文件concatenated.pest
,按照从y/list
.
包括一些检查:
#!/bin/sh
while read -r name; do
pathname="x/$name/$name.pest"
if [ ! -f "$pathname" ]; then
printf 'Can not find %s\n' "$pathname"
echo 'Output file will be incomplete'
exit 1
fi >&2
cat "$pathname"
done <y/list >concatenated.pest
答案2
回答后续略有不同的问题:
我仍然想知道如果我的子目录没有与列表中相同的名称会怎样......
让我们做一些假设:
- 的所有子目录
x
都是公平的游戏。 - 所有
.pest
文件都是公平的游戏。 - 如果您有两个
.pest
同名的文件(但位于不同的目录中),您并不关心这两个文件的编辑顺序cat
。
那么你有:
while read -r name; do
cat x/*/"$name.pest"
done <y/list >concatenated.pest
添加健全性检查有点棘手,但仍然可行。 (我不会做这一部分,因为我不知道我的假设是否符合您的用例。)
答案3
由于您可以向其提供多个文件,cat
因此最好在进行一些路径名修改后仅启动一个实例:
sed 's|.*|x/&/&.pest|' < y/filename-list.txt | xargs -d '\n' cat
解释:
sed 's|A|B|'
将所有出现的 替换A
为B
。这里 A
.*
匹配任何字符序列,无论长度或内容如何。&
in B 是与 A 匹配的整个文本的占位符。
xargs [OPTIONS...] COMMAND [ARGS...]
COMMAND [ARGS...]
将其标准输入流上的标记附加到命令后运行。通常,标记由任意数量的空白字符分隔。使用
-d
告诉xargs
我们使用不同的分隔符,在本例中\n
为换行符。如果您的
xargs
安装不支持-d
,您需要确保输入标记不包含空格。在 Linux 上,通常您将拥有xargs
支持-d
.