我想编写一个 for 循环来获取文件列表的第三个/
到第四个之间的所有内容。.
我的尝试:
for mcool_file in ./input/*.mcool; do
while IFS= read -r id; do
id | cut -d \\ -f 4- -d_ -f1-4
# Do something
done;
done
追溯:
cut: only one type of list may be specified
输入
./../input/A001C007.hg38.nodups.pairs.mcool
./../input/A001C008.hg38.nodups.pairs.mcool
所需输出
A001C007
A001C008
答案1
for pathname in input/*.mcool; do
basename "${pathname%%.*}"
done
这会迭代目录中input
以.mcool
.对于 中的每个路径名$pathname
,使用标准参数替换在第一个点处截断路径名(从 的值中${pathname%%.*}
删除与模式匹配的最长后缀字符串),然后用于提取路径名的文件名部分。.*
$pathname
basename
测试:
$ tree
.
`-- input
|-- A001C001.something.mcool
|-- A001C002.something.mcool
|-- A001C003.something.mcool
|-- A001C004.something.mcool
|-- A001C005.something.mcool
|-- A001C006.something.mcool
|-- A001C007.something.mcool
|-- A001C008.something.mcool
`-- A001C009.something.mcool
2 directories, 9 files
$ for pathname in input/*.mcool; do basename "${pathname%%.*}"; done
A001C001
A001C002
A001C003
A001C004
A001C005
A001C006
A001C007
A001C008
A001C009
这假设第一个点$pathname
出现在文件名中,而不是路径名的目录部分中,这就是为什么我不以./
.
basename
但是我们可以通过首先调用它来扭转它,以允许目录路径中包含点:
for pathname in ./input/*.mcool; do
name=$(basename "$pathname")
printf '%s\n' "${name%%.*}"
done
要是我们知道我们要删除的后缀字符串正是字符串.something.mcool
(或者.hg38.nodups.pairs.mcool
在您的情况下),那么最好的解决方案可能是这样的
for pathname in ./input/*.something.mcool; do
basename "$pathname" .something.mcool
done
...它用于basename
从路径名中删除已知后缀并一次性返回路径名的文件名部分,一次一个路径名。
basename
通过支持非标准-a
和选项(用于处理多个文件并从每个文件中删除固定后缀字符串)的实现-s
,如果没有太多文件需要处理,您甚至可以根本不使用循环:
$ basename -a -s .something.mcool ./input/*.something.mcool
A001C001
A001C002
A001C003
A001C004
A001C005
A001C006
A001C007
A001C008
A001C009
请参阅basename(1)
您系统上的手册。
答案2
和zsh
:
print -rC1 -- input/*.mcool(N:t:r:r:r:r)
(:t
修改器让你得到尾巴,:r
以及根(删除文件的扩展名,就像在 csh 或 vim 中一样)。
或者:
set -o histsubstpattern
print -rC1 -- input/*.mcool(N:t:s/.*//)
或者:
(){print -rC1 -- ${@/.*}} input/*.mcool(N:t)
(使用 ksh-style${var/pattern[/replacement]}
而不是 csh-style :s/foo/bar/
,此处关于传递给匿名函数的参数,另请参阅${@%%.*}
ksh)。
答案3
如果所有输入看起来像
./../input/A001C007.hg38.nodups.pairs.mcool
那么最简单的方法可能是:
start cmd:> sed -e 's+^./../input/++' -e 's/\..*$//' input
A001C007
A001C008
/
如果您希望删除包括第三个在内的所有内容以及.
下一个的所有内容
start cmd:> sed -r -e 's+^([^/]*/){3}++' -e 's/\..*$//' input
A001C007
A001C008
正如您所描述的一般解决方案必须计算.
最多第三个的数量/
。
答案4
如果你知道是第三个/
和第四个.
,你也可以根据和作为分隔awk
符来使用和定义字段:/
.
awk -F'[./]' '{print $7}'