Wie lösche ich alle Dateien in zufälliger Reihenfolge?

7

Ich habe eine Reihe von Dateien, die alle mit der Konvention benannt sind file_[number]_[abcd].bin(wobei [Nummer] eine Nummer im Bereich 0-Größe des Laufwerks in MB ist). dh es ist file_0_a.bin, file_0_b.bin, file_0_c.binund file_0_d.binund dann das 0würde ein 1und so weiter.

Die Anzahl der Dateien wird zur Laufzeit anhand der Größe der Partition ermittelt. Ich muss alle erstellten Dateien löschen, aber auf pseudozufällige Weise. Löschen Sie in Blöcken mit einer Größe, die ich angeben muss , dh wo 1024 Dateien vorhanden sind, 512 und dann weitere 512.

Ich habe derzeit die folgende Funktion, die ich die erforderliche Anzahl von Malen aufrufe, aber es wird zunehmend weniger wahrscheinlich, dass eine vorhandene Datei gefunden wird, bis zu dem Punkt, an dem sie möglicherweise nie vollständig ist. Offensichtlich ist dies etwas weniger als ideal.

Was ist eine andere Methode, mit der ich alle Dateien in zufälliger Reihenfolge löschen kann?

deleteRandFile() #$1 - total number of files
{
    i=$((RANDOM%$1))
    j=$((RANDOM%3))
    file=""

    case $j in
    0)
        file="${dest_dir}/file_${i}_a.bin";;
    1)
        file="${dest_dir}/file_${i}_b.bin";;    
    2)
        file="${dest_dir}/file_${i}_c.bin";;
    3)
        file="${dest_dir}/file_${i}_d.bin";;
    esac

    if ! [[ -f $file ]]; then
        deleteRandFile $1
    else
        rm $file
    fi

    return 0;
}

Bearbeiten: Ich versuche, in zufälliger Reihenfolge zu löschen, damit ich die Dateien so weit wie möglich fragmentieren kann. Dies ist Teil eines Skripts, das zunächst ein Laufwerk mit 1-MB-Dateien füllt und diese jeweils 1024 löscht und dann die Lücke mit 1 1-GB-Datei füllt. Spülen und wiederholen Sie den Vorgang, bis Sie einige sehr fragmentierte 1-GB-Dateien haben.

Yann
quelle
Vielleicht wäre es hilfreich, wenn Sie erklären könnten, warum es wichtig ist, in welcher Reihenfolge Sie die Dateien löschen.
Nate Eldredge
@NateEldredge Sicher, ich versuche eine Festplatte zu fragmentieren und ein Dateisystem zu töten. Ich habe meine Gründe.
Yann
In zsh würden Sie die *.bin(o+functionName)Notation wie in unix.stackexchange.com/a/9831 verwenden
ignis

Antworten:

13

Wenn Sie alle Dateien löschen möchten , können Sie auf einem GNU-System Folgendes tun:

cd -P -- "$destdir" &&
  printf '%s\0' * | # print the list of files as zero terminated records
    sort -Rz |      # random sort (shuffle) the zero terminated records
    xargs -r0 rm -f # pass the input if non-empty (-r) understood as 0-terminated
                    # records (-0) as arguments to rm -f

Wenn Sie nur eine bestimmte Anzahl von Personen löschen möchten, die einem regulären Ausdruck entsprechen, fügen Sie so etwas zwischen sortund ein xargs:

awk -v RS='\0' -v ORS='\0' -v n=1024 '/regexp/ {print; if (--n == 0) exit}'

Mit zshkönnten Sie tun:

shuffle() REPLY=$RANDOM
rm -f file_<->_[a-d].bin(.+shuffle[1,1024])
Stéphane Chazelas
quelle
Ich nehme nicht an, dass es Ihnen etwas ausmacht, etwas ausführlicher zu erklären?
Yann
Ich muss lernen, schneller zu tippen, oder die Überprüfungswarteschlangen ignorieren, um eine Antwort zu erhalten ;-)
Anthon
Das sieht ziemlich gut aus. Stört es Sie, etwas detaillierter darauf einzugehen, was die xargs -r0Flagge tut?
Yann
Danke, das Letzte ist, wie müsste ich dies ändern, damit das Los nicht sofort gelöscht wird, sondern beispielsweise 1024 gleichzeitig gelöscht wird? Würde es funktionieren, wenn Sie es durch etwas leiten, um die ersten 1024 Einträge zu erhalten, die einem regulären Ausdruck entsprechen?
Yann
1
@OlivierDulac, nein. printf '%s\0' *Formatiert jedes Argument %s\0so, finddass es Punktdateien ausschließt, die Liste sortiert und keinen Prozess verzweigt. Und du kannst es tun printf '%s\0' file_*_[a-d].bin. findist möglicherweise besser, wenn Sie nur reguläre Dateien möchten, obwohl Sie auch zsh und seine Globbing-Qualifikationsmerkmale verwenden können.
Stéphane Chazelas
11

Hier ist eine mögliche Alternative mit findund shuf:

$ find $destdir -type f | shuf | xargs rm -f

Dadurch werden alle Dateien in gefunden $destdirund anschließend mit dem shufBefehl die Reihenfolge gemischt und die Liste zum xargs rm -fLöschen an weitergeleitet.

So geben Sie an, wie viele Dateien gelöscht werden:

$ find $destdir -type f | shuf | head -X | xargs rm -f

Wo -Xist die Anzahl der Dateien , die Sie zum Beispiel löschen, mögen, head -100.

slm
quelle
Es ist eine gute Antwort, aber ich kann nicht angeben, wie viele Dateien gelöscht werden sollen. (Auch ich habe nicht shufauf dem System, aber ich habe nicht angegeben, was ich hatte, so dass dies nicht aufhört, eine gute Antwort zu sein)
Yann
Ich bin verwirrt, warum müssen Sie eine Nummer für die Löschfunktion angeben?
slm
1
@ Yann4 Ich bin verwirrt, aber neugierig, dass "kein Kernel neu kompiliert werden muss" - ist das eine Art Mem, das ich verpasst habe?
Volker Siegel
2
Diese Antwort ist zumindest im Allgemeinen unsicher. findGibt durch Zeilenumbrüche getrennte Literalzeichenfolgen aus und xargsliest eine durch Shell-Anführungszeichen und Leerzeichen getrennte Liste von Namen als Eingabe. Ein böswilliger Name in der Eingabe kann dazu führen, dass etwas ganz anderes gelöscht wird, als Sie löschen möchten.
R .. GitHub STOP HELPING ICE
2
@R - Sehen Sie sich die Anforderungen für das Format der Dateinamen an, die das OP verwendet. Dies ist absolut sicher angesichts dessen!
slm