Eu tenho um arquivo strings.txt
com uma lista de strings:
GCA_001677475.1
GCA_003410275.1
GCA_002310615.1
GCA_000007405.1
GCA_000219515.3
E tenho muitos arquivos em um diretório com nomes como:
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
Preciso mover apenas os arquivos cujos nomes começam com um padrão de strings.txt
. Até agora tentei usar xargs
com mv
:
cat strings.txt | xargs -I % mv %*faa ./Data
Mas mv
não vê %*faa
como regex e tenta encontrar arquivos com esse nome exato (e é claro que não consegue encontrar nenhum). Eu também tentei usar ls
, mas funciona da mesma maneira:
cat strings.txt | xargs -I {} ls {}*faa
Então, como posso fazer isso?
Responder1
xargs bash -O nullglob -c '
for prefix do
set -- "$prefix"*.faa
[ "$#" -gt 0 ] && mv -- "$@" ./Data
done' sh <strings.txt
Isso é usado xargs
para fornecer as strings strings.txt
para um script em linha bash
em lotes.
Para cada string, o script em linha bash
testa se há algum nome de arquivo que corresponda à string no diretório atual (adicionando *.faa
ao final para criar um padrão) e, em caso afirmativo, eles são movidos para o Data
diretório, que se presume já existir .
A nullglob
opção shell é definida para o script in-line para garantir que, se o padrão construído nãonãocorresponder a qualquer coisa, o padrão será removido (em vez de retido sem expansão).
Estou testando explicitamente se o padrão corresponde porque há strings no seu exemplo que não correspondem a nenhum dos nomes de arquivo mostrados. Isso é feito definindo a lista de parâmetros posicionais como o resultado da expansão global e testando se o comprimento da lista ( $#
) é maior que zero.
Obviamente, você também poderia ter feito isso sem xargs
isso:
shopt -s nullglob
while IFS= read -r prefix; do
set -- "$prefix"*.faa
[ "$#" -gt 0 ] && mv -- "$@" ./Data
done <strings.txt
Isso ainda seriafalharse uma de suas strings de prefixo correspondesse a muitos milhares de nomes de arquivos (a mv
linha de comando ficaria muito longa). Se for esse o caso, você possivelmente usaria
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
Isso pressupõe que nem as strings de prefixo nem os nomes de arquivos contenham novas linhas incorporadas.
Responder2
Esta é uma solução possível:
cat strings.txt | xargs -I '%' find . -type f -name "%*" -exec mv -t your_path {} +
Movido GCA_000007405.1_ASM740v1_protein.faa
que é a única partida.
Responder3
Não há necessidade xargs
nem nada complicado. Se todos os arquivos estiverem no mesmo diretório, será suficiente fazer:
$ while read string; do
mv "$string"_* ./Data;
done < strings.txt
Ou, se seus nomes puderem começar com a -
ou se você tiver outros caracteres estranhos neles, use:
$ while read -r string; do
mv -- "$string"_* ./Data;
done < strings.txt
Responder4
Hack rápido e sujo:cat strings.txt| xargs -i sh -c 'mv {}* your/path/'>&/dev/null
Hack menos mais correto:export dir=$(ls -1); cat strings.txt| xargs -i sh -c 'grep "^{}" <<<$dir && mv {}* your/path'; dir=""