Verschieben Sie nur die letzten 8 Dateien in einem Verzeichnis in ein anderes Verzeichnis

7

Ich versuche, die letzten 8 Dateien aus dem DocumentsVerzeichnis in ein anderes Verzeichnis zu verschieben, aber ich möchte sie nicht einzeln in dieses bestimmte Verzeichnis verschieben. Ist es möglich, sie mit einem Ersatz des tailBefehls zu verschieben, jedoch für Verzeichnisse anstelle von Dateien? Ich meine, ich würde das gerne mit so etwas tail -8 ./Documents | mv ./Anotherdirectoryoder so machen mv tail -8 ./Documents ./Anotherdirectory.

Tatsächlich suche ich nach einer cleveren Möglichkeit, die letzten 8 Dateien (wie in aufgelistet ls) schnell (ohne jeden Namen einzugeben) in das andere Verzeichnis zu verschieben. Irgendwelche Vorschläge?

Sandra Ross
quelle
Bitte schreiben Sie auf Englisch, was Ihr Endziel ist. Es ist nicht klar aus Ihrer Frage. So verschieben Sie alle Dateien von einem Verzeichnis in ein anderes : mv dir1/* dir2.
Darksky
meinst du so etwas wie ... die letzten 8 Dateien von ls?
Zanna
@darksky Es liegt daran, dass viele Dateien im DocumentsVerzeichnis verwechselt und nicht gut organisiert sind. So habe ich beispielsweise ein Curriculum_VitaeVerzeichnis im DocumentsVerzeichnis erstellt (dh ./Documents/Curriculum_Vitae) und möchte alle Dateien, die sich auf das Thema beziehen, in dieses Verzeichnis einfügen. Es gibt jedoch viele dieser Dateien, und ich möchte sie nicht einzeln verschieben.
Sandra Ross
1
@ Zanna Ja genau !!
Sandra Ross

Antworten:

7

Sie können verwenden for, wodurch die Dateien in geordneter Weise durchlaufen werden, und wir können das Parsen der Ausgabe von findoder lsvermeiden, um Probleme mit Leerzeichen und anderen Sonderzeichen in Dateinamen zu vermeiden. Vielen Dank an @muru für die Verbesserung :)

i=0; j=$(stat ~/Documents/* --printf "%i\n" | wc -l); for k in ~/Documents/*; do if (( (j - ++i) < 8 )); then echo mv -v "$k" ~/AnotherDirectory; fi; done 

Testen Sie es zuerst mit echound entfernen Sie es dann, echoum die Dateien tatsächlich zu verschieben.

Als Skript:

#!/bin/bash
i=0
j=$(stat ~/Documents/* --printf "%i\n" | wc -l )
for k in ~/Documents/*; do
  if (( (j - ++i) < 8 )); then
    echo mv -v -- "$k" ~/AnotherDirectory
  fi
done

Entfernen Sie echonach dem Testen erneut, um die Dateien wirklich zu verschieben

Erläuterung

  • i=0 Weisen Sie die Shell an, bei 0 mit der Iteration zu beginnen
  • j=$(stat ~/Documents/* --printf "%i\n" | wc -l )Dadurch wird die Variable jauf eine Ganzzahl gesetzt, die der Gesamtzahl der Dateien im Verzeichnis entspricht. Dank Sergs Antwort auf meine eigene Frage, wie man Dateien zuverlässig zählt, egal welche Zeichen ihre Namen enthalten
  • do if (( (j - ++i) < 8 ))Testen Sie für jede Iteration der Schleife, ob das Ergebnis von jminus der Häufigkeit, mit der die Schleife ausgeführt wurde, weniger als 8 beträgt, und wenn dies der Fall ist
  • mv -v -- "$k" ~/AnotherDirectory Verschieben Sie die Datei in das neue Verzeichnis
Zanna
quelle
1
[[ $((j-$((++i)))) -lt 8 ]]==(( (j - ++i) < 8 ))
Muru
@muru Ich werde einige Klammern entfernen & danke, aber es <wird schief gehen, wenn es zehn Dateien oder mehr gibt, weil es sorts beforenicht bedeutet less thanund 10 vor 8 sortieren wird.
Zanna
1
Nee. (( ))ist arithmetischer Kontext. <vergleicht ganze Zahlen in diesem Zusammenhang, 8 <10.
16.
@muru oh ich bin jetzt wach (5 ½ Stunden hinter & mehr haha) offensichtlich hast du recht & danke
Zanna
Ich habe einen Ordner mit einer großen Anzahl von Dateien, es würde nicht funktionieren. Dieser Befehl funktioniert auch nicht wie angefordert. Ich benutze es und töte es nach einer Weile, da es alle Dateien verschiebt und nicht aufhört. Ich habe es geschafft, Hunderte zu verschieben, und dann muss ich STRG + C
drücken
3

Sie können solche Dinge mithilfe der Befehlssubstitution ausführen. In Bash:

mv $(ls -d [sort options] source/* | tail -n8) destination

Das $(command)führt alles aus, was darin enthalten ist, und ersetzt die Textausgabe durch den äußeren Befehl. Dieser lsBefehl druckt den Pfad zu jeder Datei im Quellverzeichnis, sortiert nach den von Ihnen angegebenen Flags, eines pro Zeile, sodass tailnur die letzten verwendet werden können. Somit würde sich das Obige auf erweitern

mv source/file1 source/file2 source/file3 ... source/file8 destination

Sie können einfach ausführen, um ls -d [sort options] source/* | tail -n8zu sehen, welche Dateien kopiert werden.

Abhängig davon, wie Sie die Ausgabe lsund die Dateinamen bestellen , können Sie möglicherweise das tun, wonach Sie suchen, indem Sie einfach eine Variante von verwenden, mv source/name_* destinationum alles, was mit "name_" beginnt, in das Zielverzeichnis zu kopieren.

BEARBEITEN: Das Obige wird unterbrochen, wenn die Dateinamen Leerzeichen enthalten. Eine kompliziertere Alternative, die dies anspricht, wäre

ls -d1 [sort options] source/* | tail -n8 | tr '\n' '\0' | xargs --null mv -t destination

Es wird jedoch immer noch die Parsing- lsAusgabe verwendet, um die Sortierung in einer nicht alphabetischen Reihenfolge zu erhalten.

t-mager
quelle
1

Ähnlich wie bei t-mager können Sie die Sortieroptionen von ls verwenden und die letzten 8 Dateien in eine Liste aufnehmen. Dies sind Ihre Dateien:

1 10 2 3 4 5 6 7 8 9

Verwenden Sie den folgenden Befehl:
for n in `ls|tail -8`; do mv $n ~/temp; done

xortion
quelle
1
Keine gute Idee
Zanna
@ Zanna, warum nicht? Neben dem ursprünglichen Backtick-Problem verschiebt dieser Befehl einfach die letzten 8 Dateien aus einem Verzeichnis in ein anderes und ist leicht zu verstehen.
Xortion
Es wird unterbrochen, wenn in Dateinamen Leerzeichen, Zeilenumbrüche usw. vorhanden sind. Siehe den Link, warum ich mich so sehr um meine eigene Antwort bemüht habe, wenn das Parsen lsviel offensichtlicher ist ...
Zanna
0

Ich finde, dass das auch funktioniert: ls -1 [sort options] | tail -n2 | xargs -I {} -n 1 echo "mv \"{}\" ../t2/"

Natürlich muss das Echo entfernt werden: ls -1 | tail -n2 | xargs -I {} -n 1 mv "{}" ../t2/

Das "{}"kann durch '{}' Tatsächlich ersetzt werden. Als letztes Experiment funktioniert auch das Entfernen der (doppelten) Anführungszeichen. Überraschend, aber getestet.

tpb261
quelle