Wie verschiebe ich 30 GB an Dateien aus einem Ordner mit 80 GB an Dateien?

Wie verschiebe ich 30 GB an Dateien aus einem Ordner mit 80 GB an Dateien?

Ich habe einen Ordner mit mehr als 500 Videos und die Ordnergröße beträgt etwa 80 GB.

Ich möchte 30 GB Videos in einen anderen Ordner verschieben, aber wie?

Ich verwende ein Terminal und kann keine GUI installieren.

Antwort1

Unselektiv(automatisch)

Mir ist kein einziges Kommandozeilentool bekannt, das das kann ... Aber man kann ein Skript verwenden, um Dateien zu verschieben, bis eine bestimmte Gesamtgröße erreicht ist, z. B. so (Führen Sie das Skript nur einmal aus. Bei erneuter Ausführung verschiebt es die angegebene Größe erneut aus den verbleibenden Dateien.):

#!/bin/bash

sourc_dir="/path/to/directory" # Set the path to the source directory "no trailing /"
dest_dir="/path/to/directory" # Set the path to the destination directory "no trailing /"
move_size="30" # Set the total size of files to move in Gigabytes
 
# Don't edit below this line
move_size=$(( move_size * 1000000 ))
current_size=$(du -sk "$sourc_dir" | awk '{printf "%d", $1}')
remaining_size=$(( current_size - move_size ))

for f in "$sourc_dir"/*; do
  [ -f "$f" ] || continue
  new_size=$(du -sk "$sourc_dir" | awk '{printf "%d", $1}')
  (( new_size <= remaining_size )) && exit
  mv -n -- "$f" "$dest_dir"/
  done

Oder sogar ein Einzeiler(keine Script-Datei nötig), das Sie im Terminal beispielsweise wie folgt ausführen können:

for f in /path/to/source/*; do [ -f "$f" ] || continue; (( size >= (30*(1000**3)) )) && break || (( size += $(stat --printf "%s" "$f") ))  && mv -n -- "$f" /path/to/destination/; done

Möglicherweise möchten Sie unset sizees in derselben Shell-Instanz erneut ausführen können.

Selektiv(manuell)

Sie können jederzeit ein Shell-Muster oder eine Pipe aus einem Suchtool basierend auf Dateinamen, Größen, Typen usw. angeben.

Oder, bequemer, Sie können einen konsolenbasierten Dateimanager verwenden, der die Auswahl mehrerer Dateien unterstützt, wie z. B. den bekannten und funktionsreichenGNU Midnight CommanderDas ist in den offiziellen Ubuntu-Repositories verfügbar und kann wie folgt installiert werden:

sudo apt install mc

und um es auszuführen, geben Sie ein mcund drücken Sie Enter.... Ihnen wird dann eine navigierbare Benutzeroberfläche angezeigt, in der Sie mithilfe der InsertTastenkombination mehrere Dateien auswählen können ... Sie können die Gesamtgröße der ausgewählten Dateien und ihre Anzahl in Echtzeit wie folgt sehen:

Bildbeschreibung hier eingeben

Wenn Sie alle zu verschiebenden Dateien ausgewählt haben, drücken Sie die F6entsprechende Taste auf der Tastatur, um das Dialogfeld „Verschieben/Umbenennen“ zu öffnen und das Zielverzeichnis einzugeben. Wählen Sie anschließend die Option [< OK >]zum gleichzeitigen Verschieben der ausgewählten Dateien wie folgt aus:

Bildbeschreibung hier eingeben

Oder auch die weniger bekannten mit weniger FunktionenF f f (Verdammt schneller Dateimanager):-) ... Das ist interessanterweise so geschrieben bash... Obwohl es die Auswahl mehrerer Dateien unterstützt, müssen Sie es unter Umständen ein wenig anpassen, um die Gesamtgröße der ausgewählten Dateien sehen zu können. Als schnelle Lösung können Sie beispielsweise die folgende Zeile 159in der Quelldatei ändern fff:

local mark_ui="[${#marked_files[@]}] selected (${file_program[*]}) [p] ->"

dazu:

local mark_ui="[${#marked_files[@]}] $(for f in "${marked_files[@]}"; do (( tsize += $(stat --printf "%s" "$f") )); done; tsize=$((tsize/(1000**2))); printf '[%d M]' "$tsize";) selected (${file_program[*]}) [p] ->"

Dann können Sie die Datei einfach wie folgt ausführen (Keine Installation nötig):

bash fff

Oder sehen Sie sich die Hilfe zur Verwendung wie folgt an:

bash fff -h

Dann müssen Sie nur noch zu Ihrem Quellverzeichnis navigieren und mit der Auswahl der zu verschiebenden Dateien beginnen m(Kleinbuchstaben)-Taste wie folgt:

Bildbeschreibung hier eingeben

Wenn Sie mit der Dateiauswahl fertig sind, navigieren Sie zum Zielverzeichnis und verschieben Sie die zuvor ausgewählten Dateien dorthin, indem Sie auf die Schaltfläche p(Kleinbuchstaben) Tastaturtaste.

Antwort2

Hier ist eine Alternative zuRaffaDie Idee von erfordert nicht dufür jede Datei ein auf dem gesamten Verzeichnis. Stattdessen wird ein statauf jeder Datei ausgeführt.einmal, wobei find's verwendet werden, -printf %sum die Größe und %pden Pfad zur zu verschiebenden Datei abzurufen.

#!/bin/bash

src='foo'
dest='bar'

# 30GB in bytes to move:
(( bytestomove=30*(1000**3) ))
movedbytes=0

while IFS=$'\t' read -r -d '' bytes file
do
    # if we already moved enough, break out
    (( movedbytes >= bytestomove )) && break;

    # try to move it, break out if it fails
    mv -n -- "$file" "$dest" || break

    # successfully moved, add bytes to movedbytes
    (( movedbytes += bytes ))
done < <(find "$src" -type f -printf "%s\t%p\0")

(( movedmegs=movedbytes/(1000**2) ))
printf "Moved %d MB\n" $movedmegs

Antwort3

@TedLyngmo wies darauf hin, dass die Tar-Lösung, die ich zuerst vorgestellt habe, die Dateien effektiv kopiert und nicht verschiebt. Diese Unterscheidung ist aus zwei Gründen wichtig:

  1. Bei einer Kopie bleiben die Quelldateien erhalten, während bei einer Verschiebung die Quelldateien nicht mehr an ihren Quellspeicherorten vorhanden sind.
  2. Wenn Dateien innerhalb desselben Dateisystems verschoben werden, wie es in dieser Frage der Fall sein kann, mvwird die Quelldatei einfach mit dem neuen Speicherort verknüpft und der Inhalt überhaupt nicht kopiert. Dies ist in der Regel deutlich schneller als das Kopieren, insbesondere bei großen Dateien.

Szenario verschieben

Wir können weiterhin die tarKonzepte des ursprünglich angegebenen Kopierszenarios verwenden, um eine Dateiliste mit nur den ersten 30 GB der targefundenen Dateien zu erstellen und dann nur diese Dateien zu verschieben:

#!/bin/bash

# Convert human-readable number, e.g. 1M, 30G to number of 1024 byte blocks 
limit=$(numfmt --from=auto $1 --to-unit 1024)
src_dir=$2
dest_dir=$3

mkdir $dest_dir
filelist=$(readlink -f $(mktemp -p $dest_dir))

# create a list of files to be moved.  tar -v outputs filenames to stdout, and 
# the dest archive is /dev/null
tar -v -L $limit -F false -c -f /dev/null -C $src_dir . > $filelist 2> /dev/null
tar_result=$?
if [ "$tar_result" = 2 ]; then
    echo "$1 limit was hit - some unmoved files will remain in $dest_dir"
else
    echo "All files will be moved"
fi

pushd $dest_dir > /dev/null
abs_dest_dir=$PWD
# create directories in the destination
grep '/.*/$' $filelist | xargs mkdir -p
popd > /dev/null

pushd $src_dir > /dev/null
# create hard links in the destination
grep -v '/$' $filelist | xargs cp -l --parents -t $abs_dest_dir
# unlink source files
grep -v '/$' $filelist | xargs rm
# remove source directories in reverse order, if they are empty
grep '/.*/$' $filelist | tac | xargs rmdir --ignore-fail-on-non-empty
popd > /dev/null

rm $filelist

Das ist komplexer als ich möchte:

  • mvbietet nicht so viel Kontrolle über Quell- und Zielpfade für mehrere Dateien (insbesondere kein Analogon zur cpOption --parents), daher werden die Dateien verschoben, indem Hardlinks an den Zielorten erstellt und die Verknüpfungen der Quelldateien dann aufgehoben werden

  • Da Quellverzeichnisse eine Mischung aus Einträgen enthalten, die verschoben werden sollen und solchen, die nicht verschoben werden sollen, müssen Verzeichnisse im Ziel neu erstellt und nicht einfach (mitsamt dem gesamten Inhalt) verschoben werden. Daher werden die entsprechenden Zielverzeichnisse vor dem Verschieben von Dateien erstellt und die entsprechenden Quellverzeichnisse nach dem Verschieben von Dateien gelöscht, wenn sie leer sind.

Vorbehalte

  • tar -vgibt einen Dateieintrag pro Zeile aus. Dies schlägt fehl, wenn die Pfadnamen Sonderzeichen enthalten, z. B. Zeilenumbrüche. Hoffentlich sind die Quellpfadnamen sinnvoll.

  • Dabei werden etwas weniger als 30 GB an tatsächlichen Dateidaten verschoben, da der Stream sowohl Metadaten (Dateinamen, Zeitstempel usw.) als auch die eigentlichen Inhalte enthält und für all dies die 30-GB-Begrenzung gilt.

  • Ich gehe hier etwas locker mit KB vs. kb um. Da der -LParameter mit Einheiten von 1024 Bytes arbeitet, begrenzt dies die Verschiebung tatsächlich auf 3.072.000.000 Bytes Tar-Stream. Passen Sie die Zahlen entsprechend an.

  • filelist.txt wird im aktuellen Verzeichnis erstellt. Hierfür sind Schreibberechtigungen erforderlich. Dies ist wahrscheinlich eine Selbstverständlichkeit, da für die Verschiebungsvorgänge ohnehin Schreibberechtigungen erforderlich sind.

Szenario kopieren

Sie können tarIhren Ordner in einen Stream umwandeln und tarden Stream dann wieder in Dateien an einem neuen Speicherort umwandeln. Die erste tarMethode -Lbegrenzt die „Bandlänge“ auf 3000000 KB, bevor ein neues Band angefordert wird. tarverwendet -F, um nach jedem „Band“ zu laufen false. Da falseein Fehler zurückgegeben wird, wird die Übertragung nach dem ersten „Band“, also nach 30 GB, beendet. Alle Daten durch nur 2 Aufrufe von Tar zu leiten, sollte schneller sein, als alle Dateien mit Bash-Schleifen zu durchlaufen.

mkdir dest.dir
tar -cv -L 3000000 -F false -C src.dir . | tar -x -C dest.dir/

Dadurch werden die Dateien kopiert, bis die Grenze von 30 GB erreicht ist. Anschließend tarwird folgender Fehler ausgegeben:

tar: Unexpected EOF in archive
tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now
tar: ‘false’ command failed
tar: Error is not recoverable: exiting now

tarüberträgt die Datei nicht, die übertragen wurde, als das Limit erreicht wurde – sie wird überhaupt nicht in das Ziel geschrieben.

Vorbehalte

  • Dabei werden etwas weniger als 30 GB der tatsächlichen Dateidaten kopiert, da der Stream sowohl Metadaten (Dateinamen, Zeitstempel usw.) als auch die eigentlichen Inhalte enthält und für all dies die 30-GB-Begrenzung gilt.

  • Ich gehe hier etwas locker mit KB vs. kb um. Da der -LParameter mit Einheiten von 1024 Bytes arbeitet, begrenzt dies die Übertragung tatsächlich auf 3.072.000.000 Bytes Tar-Stream. Passen Sie die Zahlen entsprechend an.


Frühere Bearbeitungen dieser Antwort verwendeten find-cpio-head-cpio und dann tar-head-tar. Die jetzt vorgestellte Tar-Tar-Lösung sollte ausreichen, aber überprüfen Sie bitte den Bearbeitungsverlauf, wenn die anderen Lösungen von Interesse sind.

Antwort4

Gehen Sie zu dem Ordner, in dem sich Ihre Dateien befinden:

cd SOURCE_FOLDER

Erstellen Sie eine Liste der Dateien in diesem Ordner

ls > list.txt

Bearbeiten Sie es in einem beliebigen Editor und entfernen Sie Dateien, die Sie NICHT verschieben möchten. Speichern Sie das Ergebnis, sodass list.txt jetzt nur die Dateien enthält, die Sie verschieben möchten. Führen Sie nun dieses einfache Skript aus, das jede Zeile aus Ihrer list.txt-Datei liest und diese Datei in Ihr Zielverzeichnis verschiebt.

while IFS= read -r line; do mv "$line" ../DESTINATION_DIRECTORY/"$line"; done < list.txt

verwandte Informationen