strings.txt
我有一个包含字符串列表的文件:
GCA_001677475.1
GCA_003410275.1
GCA_002310615.1
GCA_000007405.1
GCA_000219515.3
我的目录中有许多文件,其名称如下:
GCA_000005845.2_ASM584v2_protein.faa
GCA_000006925.2_ASM692v2_protein.faa
GCA_000007405.1_ASM740v1_protein.faa
GCA_000007445.1_ASM744v1_protein.faa
GCA_000008865.2_ASM886v2_protein.faa
GCA_000009565.2_ASM956v1_protein.faa
我只需要移动那些名称以strings.txt
.到目前为止,我已经尝试使用xargs
with mv
:
cat strings.txt | xargs -I % mv %*faa ./Data
但mv
不%*faa
视为正则表达式并尝试查找具有该确切名称的文件(当然它找不到任何文件)。我也尝试过使用,ls
但它的工作方式是相同的:
cat strings.txt | xargs -I {} ls {}*faa
那么我该怎么做呢?
答案1
xargs bash -O nullglob -c '
for prefix do
set -- "$prefix"*.faa
[ "$#" -gt 0 ] && mv -- "$@" ./Data
done' sh <strings.txt
这用于xargs
将字符串批量提供strings.txt
给内联bash
脚本。
对于每个字符串,内联bash
脚本测试当前目录中是否有与该字符串匹配的文件名(添加*.faa
到末尾以创建模式),如果有,则将这些文件移动到该Data
目录,假设该目录已经存在。
为内联脚本设置shellnullglob
选项,以确保构造的模式是否不是匹配任何内容,模式将被删除(而不是保留未扩展)。
我正在明确测试模式是否匹配,因为您的示例中的某些字符串与您显示的任何文件名都不匹配。这是通过将位置参数列表设置为全局扩展的结果,然后测试列表的长度 ( $#
) 是否大于零来完成的。
显然你也可以这样做,而不像xargs
这样:
shopt -s nullglob
while IFS= read -r prefix; do
set -- "$prefix"*.faa
[ "$#" -gt 0 ] && mv -- "$@" ./Data
done <strings.txt
这仍然会失败如果您的前缀字符串之一碰巧匹配数千个文件名(mv
命令行会变得太长)。如果是这种情况,您可能会使用
shopt -s nullglob
while IFS= read -r prefix; do
set -- "$prefix"*.faa
if [ "$#" -gt 0 ]; then
printf '%s\n' "$@" | xargs sh -c 'mv -- "$@" ./Data' sh
fi
done <strings.txt
这是假设前缀字符串和文件名都不包含嵌入的换行符。
答案2
这是一个可能的解决方案:
cat strings.txt | xargs -I '%' find . -type f -name "%*" -exec mv -t your_path {} +
感动GCA_000007405.1_ASM740v1_protein.faa
那是唯一的匹配。
答案3
不需要xargs
或任何复杂的事情。如果所有文件都位于同一目录中,则执行以下操作就足够了:
$ while read string; do
mv "$string"_* ./Data;
done < strings.txt
或者,如果您的名字可以以 a 开头-
,或者其中可能有其他奇怪的字符,请使用:
$ while read -r string; do
mv -- "$string"_* ./Data;
done < strings.txt
答案4
快速而肮脏的黑客:cat strings.txt| xargs -i sh -c 'mv {}* your/path/'>&/dev/null
更少更正确的黑客:export dir=$(ls -1); cat strings.txt| xargs -i sh -c 'grep "^{}" <<<$dir && mv {}* your/path'; dir=""