Ich habe eine Datei strings.txt
mit einer Liste von Zeichenfolgen:
GCA_001677475.1
GCA_003410275.1
GCA_002310615.1
GCA_000007405.1
GCA_000219515.3
Und ich habe viele Dateien in einem Verzeichnis mit Namen wie:
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
Ich muss nur die Dateien verschieben, deren Namen mit einem Muster von beginnen strings.txt
. Bisher habe ich versucht, xargs
mit zu verwenden mv
:
cat strings.txt | xargs -I % mv %*faa ./Data
Aber mv
es wird nicht %*faa
als regulärer Ausdruck angesehen und versucht, Dateien mit genau diesem Namen zu finden (und kann natürlich keine finden). Ich habe auch versucht, Folgendes zu verwenden, ls
aber es funktioniert genauso:
cat strings.txt | xargs -I {} ls {}*faa
Wie kann ich das also machen?
Antwort1
xargs bash -O nullglob -c '
for prefix do
set -- "$prefix"*.faa
[ "$#" -gt 0 ] && mv -- "$@" ./Data
done' sh <strings.txt
Dies dient dazu, die Zeichenfolgen stapelweise an ein Inline- Skript xargs
weiterzugeben .strings.txt
bash
Das Inline- bash
Skript prüft für jeden String, ob im aktuellen Verzeichnis Dateinamen vorhanden sind, die mit dem String übereinstimmen (durch Anhängen *.faa
an das Ende entsteht ein Muster). Ist dies der Fall, werden diese in das Verzeichnis verschoben Data
, von dem angenommen wird, dass es bereits existiert.
Die nullglob
Shell-Option wird für das Inline-Skript gesetzt, um sicherzustellen, dass das erstellte MusternichtWenn etwas übereinstimmt, wird das Muster entfernt (anstatt unverändert beizubehalten).
Ich teste explizit, ob das Muster passt, da es in Ihrem Beispiel Zeichenfolgen gibt, die keinem der von Ihnen angezeigten Dateinamen entsprechen. Dies geschieht, indem die Liste der Positionsparameter auf das Ergebnis der Glob-Erweiterung gesetzt und dann getestet wird, ob die Länge der Liste ( $#
) größer als Null ist.
Natürlich hättest du das auch ohne machen können, und xargs
zwar so:
shopt -s nullglob
while IFS= read -r prefix; do
set -- "$prefix"*.faa
[ "$#" -gt 0 ] && mv -- "$@" ./Data
done <strings.txt
Dies würde immer nochscheiternwenn einer Ihrer Präfix-Strings zufällig mit vielen tausend Dateinamen übereinstimmt (die mv
Befehlszeile würde zu lang werden). In diesem Fall würden Sie möglicherweise verwenden
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
Dies setzt voraus, dass weder Präfixzeichenfolgen noch Dateinamen eingebettete Zeilenumbrüche enthalten.
Antwort2
Dies ist eine mögliche Lösung:
cat strings.txt | xargs -I '%' find . -type f -name "%*" -exec mv -t your_path {} +
Verschoben GCA_000007405.1_ASM740v1_protein.faa
, das ist die einzige Übereinstimmung.
Antwort3
Das ist nicht nötig xargs
und auch nichts Kompliziertes. Wenn sich alle Dateien im selben Verzeichnis befinden, sollte es ausreichen, Folgendes zu tun:
$ while read string; do
mv "$string"_* ./Data;
done < strings.txt
Oder, wenn Ihre Namen mit einem „a“ beginnen können -
oder andere seltsame Zeichen enthalten, verwenden Sie:
$ while read -r string; do
mv -- "$string"_* ./Data;
done < strings.txt
Antwort4
Schneller und einfacher Hack:cat strings.txt| xargs -i sh -c 'mv {}* your/path/'>&/dev/null
Weniger richtiger Hack:export dir=$(ls -1); cat strings.txt| xargs -i sh -c 'grep "^{}" <<<$dir && mv {}* your/path'; dir=""