Wie verschiebe ich alle Dateien, deren Namen mit einer Zeichenfolge beginnen, aus einer Liste?

Wie verschiebe ich alle Dateien, deren Namen mit einer Zeichenfolge beginnen, aus einer Liste?

Ich habe eine Datei strings.txtmit 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, xargsmit zu verwenden mv:

cat strings.txt | xargs -I % mv %*faa ./Data

Aber mves wird nicht %*faaals 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, lsaber 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 xargsweiterzugeben .strings.txtbash

Das Inline- bashSkript prüft für jeden String, ob im aktuellen Verzeichnis Dateinamen vorhanden sind, die mit dem String übereinstimmen (durch Anhängen *.faaan 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 nullglobShell-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 xargszwar 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 mvBefehlszeile 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 xargsund 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=""

verwandte Informationen