Löschen Sie den Inhalt der Datei, behalten Sie jedoch Name und Hierarchie bei

7

Ich habe eine Verzeichnisstruktur gespiegelt, aber der Inhalt der Dateien ist mir egal, ich möchte nur den Namen und die Struktur von allem beibehalten.

Wie kann ich den Inhalt aller Dateien (nicht Ordner) durch "nichts" ersetzen (null, 1 Byte, leere Zeichenfolge oder ähnliches)?

Hensti
quelle
Sind Sie auf einem Linux-System?
Jeff Schaller
@ JeffSchaller OS X
Hensti
@ JeffSchaller Ich glaube nicht, dass dies mit dem Kernel zusammenhängt. Tools: Gnu vs BSD vs UNIX, kann von Relevanz sein.
Strg-Alt-Delor
Die Tools sind relevant. Wenn Sie alle Metadaten speichern möchten, können Sie sich meine Antwort ansehen, in der erläutert wird, wie dies funktioniert star.
schily
@ ctrl-alt-delor Ich stimme zu, dass der Kernel nicht wichtig ist; Ich fragte nach dem Betriebssystem als Abkürzung / Hinweis auf die verfügbaren Tools (ich hatte es truncateim Sinn, führte aber mit einer POSIX-Option aus).
Jeff Schaller

Antworten:

18

Generell

find /top -type f -exec cp /dev/null {} \;

oder (mit freundlicher Genehmigung von Jordanm ):

find /top -type f -exec sh -c '> $1' -- {} \; 

Auf einem Linux-System (oder einem mit dem Befehl truncate aus dem GNU coreutils-Paket ):

find /top -type f -exec truncate -s 0 {} +
Jeff Schaller
quelle
3
Einer noch? find /top -type f -exec sh -c '> $1' -- {} \;
Jordan
@ JeffSchaller Danke. Ich denke, alle Daten außer dem Änderungsdatum bleiben gleich. Kannst du bestätigen? (Das Erstellungsdatum, die chmod-Attribute usw. ändern sich nicht).
Rahul
Schnellere und platzdatensamensichere Variante:find /top -type f -print0 | xargs -r0 truncate -s0
Simon Richter
@SimonRichter Alle 3 vorhandenen Befehle können sicher mit beliebigen Dateinamen ausgeführt werden - testen Sie sie und sehen Sie!
Jeff Schaller
1
@ Rahul, ich muss kein OSX-System bestätigen, aber die cpVersion sollte den Besitzer / die Berechtigung nicht ändern. Alle Befehle würden die Änderungszeit aktualisieren. Das Erstellungsdatum hätte keinen Grund, sich zu ändern, aber das kann ich nicht testen.
Jeff Schaller
6

Mit zsh:

for f (**/*(D.)) : > $f

.dies nur für reguläre Dateien zu tun, Dversteckte Dateien und Dateien in versteckte Verzeichnisse aufzunehmen.

Für eine kleine Anzahl von Dateien können Sie es auf kürzen :>**/*(D.).

So behalten Sie die gleiche Größe für die Dateien bei, machen sie jedoch spärlich ohne Daten (daher findet sie nur auf der Festplatte statt, außer im Apple HFS + -Dateisystem, das keine spärlichen Dateien unterstützt):

find . -type f -exec perl -e '
  for (@ARGV) {
    unless (open F, "+<", $_) {warn "open $_: $!"; next}
    unless (seek F, 0, 2) {warn "seek $_: $!"; next}
    $size = tell F;
    unless (truncate F, 0) {warn "zap $_: $!"; next}
    unless (truncate F, $size) {warn "fill $_: $!"; next}
  }' {} +

Beachten Sie, dass alle diese Dateien die letzte Änderungszeit der Dateien aktualisieren.

Stéphane Chazelas
quelle
1

Wenn Sie alle Metadaten für die Dateien behalten möchten, empfehle ich Folgendes:

  • Archivieren Sie zuerst die Metadaten der Dateien mit:

    star -c -dump -meta $STARTDIR > out.tar

  • Rufen Sie dann findauf, um die Dateien zu entfernen.

Mit Star können Sie extractdie Metadaten aus einem solchen Teerarchiv aufrufen, indem Sie Folgendes aufrufen:

star -xp -xmeta < out.tar

Dadurch wird ein Verzeichnisbaum erstellt, der dem ursprünglichen Baum ähnelt, aber alle einfachen Dateien haben dann die Größe 0.

Wenn Sie anrufen:

star -xp -xmeta -force-hole < out.tar

Die Dateien sind alle spärliche Dateien ohne Inhalt, aber mit der richtigen Dateigröße.

Beachten Sie, dass die starMethode auch dann von Interesse sein kann, wenn Sie ein Problem einem Softwareautor melden müssen und das Problem nur bei einem bestimmten Dateibaum auftritt und Sie den Inhalt der Dateien nicht preisgeben möchten.

schily
quelle
1

Der Vollständigkeit halber hier die Bash-Version:

for f in **; do [ -f "$f" ] && [ ! -L "$f" ] && >"$f"; done

Dies erfordert die globstarOption enabled ( shopt -s globstar) und daher mindestens Bash-Version 4. (Wenn Sie jedoch wissen, wo zshSie sie verwenden möchten, möchten Sie wahrscheinlich auch nicht an der Standardversion von Mac OS X festhalten.)

David Ongaro
quelle
Sie möchten Symlinks ausschließen, da diese außerhalb des Verzeichnisbaums und der Fifos verweisen können, da dies hängen bleibt. Es macht wenig Sinn, dies für andere Arten von nicht regulären Dateien zu tun, und kann für einige Arten von Gerätedateien gefährlich sein (zum Beispiel würde es das System für einen / dev / watchdog neu starten). Sie haben auch vergessen, Ihre Variablen anzugeben, was für zsh, aber nicht für bash in Ordnung ist. Beachten Sie auch, dass versteckte Dateien übersprungen werden.
Stéphane Chazelas
IMHO, [ -f "$f" ] && >"$f"wäre etwas sicherer, da es die Kürzung einschränkt, nur auf reguläre Dateien (nicht auf Nicht-Verzeichnisse) zu reagieren.
Kusalananda
1
@Kusalananda, Symlinks wären immer noch ein Problem. Sie benötigen:[ -f "$f" ] && [ ! -L "$f" ] && > "$f"
Stéphane Chazelas
@ StéphaneChazelas: Ok, ich habe deinen Vorschlag angewendet. (Leider findsieht die Lösung jetzt einfacher aus)
David Ongaro