Skript zum Speichern bestimmter Verzeichnisse, die eine TXT-Datei enthalten, und zum Löschen der Dateien aus den anderen Verzeichnissen ohne die bestimmte TXT-Datei [geschlossen]

0

Ich bin fast fertig mit dem Skript, aber dies gibt Verzeichnisse aus. Was ich möchte, ist eine Ausgabe von Dateien. Wie auch immer, einer von euch will mir helfen? :)

    #!bin/bash
( find /testftp/* -type d ;
  find /testftp/* -type f -iname DONOTDELETE.TXT -printf '%h'
) | sort | uniq -u

Ausgabe ist:

/testftp/logs

Die Ausgabe ist das Verzeichnis, in dem DONOTDELETE.TXT nicht vorhanden ist. Es ist ziemlich nah. Müssen nur die Dateien anzeigen.

JoyIan Yee-Hernandez
quelle
(1) Sie möchten Dateien nur in einem Verzeichnis löschen , das nicht über DONOTDELETE.TXT verfügt, nicht jedoch das Verzeichnis selbst? (2) Welchen Verzeichnissatz zeigt der printf jetzt an? Die mit der TXT-Datei oder die ohne?
ADTC
(1) Ja! (2) printf zeigt das Verzeichnis an, in dem die Datei DONOTDELETE.TXT NICHT existiert. ABER es zeigt auch "/ testftp" an, welches das Verzeichnis ist, das die anderen Unterverzeichnisse enthält. Also es ist ziemlich nah, aber ich verliere jetzt LOL
JoyIan Yee-Hernandez
Versuchen Sie es -exec list {}/*statt -printf '%h'. Wenn es die richtigen Dateien zeigt nur , vielleicht können Sie versuchen -exec rm -f {}/*( Achtung: Diese gefährlich! ). Auch das kann nützlich sein.
ADTC
Mit diesem Code ( find /testftp -type d ; find /testftp -type f -iname DONOTDELETE.TXT -exec list {} \; ) | sort | uniq -u wird ausgegeben: `find: list: Keine solche Datei oder Verzeichnis / testftp / testftp / logger / testftp / logs` DONOTDELETE.TXT ist unter `/ testftp /
logger`
Sorry, das hätte lsnicht sein sollen list(immer vergessen!)
ADTC

Antworten:

1

Hier ist meine Meinung dazu:

#! /bin/bash

SPECIAL_FILE=DONOTDELETE
LOGFILE=clean.$(date +"%Y-%d-%m.%H%M%S").log   
FIND_BASE="$1"
if [ $# -ne 1 ]; then
        echo "Syntax $(basename $0) <FIND_BASE>"
        exit 1
fi
if [ "$FIND_BASE" = "." ]; then
        FIND_BASE=$(pwd)
else
        FIND_BASE=$(pwd)/$FIND_BASE
fi

for d in $(find $FIND_BASE -type d -print); do
        if [ "$d" != "$FIND_BASE" ]; then
                ls $d | grep $SPECIAL_FILE &> /dev/null
                if [ $? -ne 0 ]; then
                        echo "Deleting $d" | tee -a $LOGFILE
                        rm -rf $d 2>/dev/null
                else
                        echo "Ignoring $d, contains $SPECIAL_FILE" | tee -a $LOGFILE
                fi
        fi
done
exit 0

Fügen Sie dies einem Skript hinzu, ändern Sie die Variablen nach Belieben mit Ihrer eigenen Namenskonvention (für die spezielle Datei und den Protokollnamen) und rufen Sie sie dann einfach mit dem Startverzeichnispfad als Parameter auf. Es schließt alle Verzeichnisse aus, die die gewünschte Datei enthalten, und löscht alle anderen.

Yanick Girouard
quelle
1

Ich dachte, ich würde es versuchen.


#!/bin/bash
# file name and path can not have spaces for this to work.

ignorefile=DONOTDELETE.TXT
dir="`find /testftp/* -type d`";
exists=$(ls $dir | for each in $(find $dir -type f -iname $ignorefile -printf '%h\n'); do echo -en "grep -v $each |" ; done | sed '$s/.$//') 
direxists=$(ls $dir | eval $exists | grep -v $ignorefile | sed 's/:/\//g' | sort | uniq -u)

for pth in $direxists; 
do 
if [ -d $pth ]; then 
if [ "$(ls -A $pth)" ]; then 
echo rm -f ""$pth*""
fi
fi
done

reproduzieren:
geändert dir = "` find / testftp / * -type d` ";
zu
dir = "` find ./testftp/* -type d` ";

mkdir testftp & cd testftp
für x in 1 2 3 4 5 6 7 8 9; do mkdir $ x; erledigt
für y in 1 2 3 4 6 7 9; Berühre $ y / blah; erledigt
Berühren Sie 5 / DONOTDELETE.TXT
Berühren Sie 5 / some.log
Berühren Sie 8 / DONOTDELETE.TXT
Berühren Sie 8 / another.file

cd ..
$ ./script.sh 
rm -f ./testftp/1/blah
rm -f ./testftp/2/blah
rm -f ./testftp/3/blah
rm -f ./testftp/4/blah
rm -f ./testftp/6/blah
rm -f ./testftp/7/blah
rm -f ./testftp/9/blah

tao
quelle
Ich habe es versucht. `#! / bin / bash # Dateiname und Pfad dürfen keine Leerzeichen enthalten, damit dies funktioniert. ignorefile = DONOTDELETE.TXT dir = " find ./testftp/* -type d"; exists = $ (ls $ dir | für jeden in $ (find $ dir -type f -iname $ ignorefile -printf '% h \ n'); do echo -en "grep -v $ each |"; done | sed ' $ s /.$// ') direxists = $ (ls $ dir | eval $ existiert | grep -v $ ignorefile | sed' s /: / \ // g '| sort | uniq -u) für pth in $ direxists ; do if [-d $ pth]; dann wenn ["$ (ls-A $ pth)"]; dann echo rm -f "" $ pth * "" fi fi done `Aber es hat nichts getan :(
JoyIan Yee-Hernandez
irgendwelche Gedanken? :)
JoyIan Yee-Hernandez
Was du hier wieder eingefügt hast und was ich dort aufgestellt habe, sind 2 verschiedene Dinge. und wenn Sie Cygwin / Windows verwenden, vergessen Sie es
Tao
0

Wenn Sie Bash 4+ haben (überprüfen Sie mit bash --version), können Sie dies in einem Zweizeiler tun:

shopt -s globstar
for f in ./**/; do [[ -f "$f"/DONOTDELETE.TXT ]] || rm -f "$f"/*; done

Beachten Sie, dass shopt -s globstares in einer eigenen Zeile stehen muss - stellen Sie es nicht einfach vor die for-Schleife mit einem ;.

./**/wird in alle Unterverzeichnisse des aktuellen Verzeichnisses und deren Unterverzeichnisse rekursiv erweitert. Wenn Sie nur eine Ebene in den Baum gehen möchten, verwenden Sie ./*/stattdessen (und kümmern Sie sich nicht darum, globstar einzustellen). Wenn Sie eine feinere Kontrolle wünschen, müssen Sie findstattdessen damit herumspielen (insbesondere mit den Optionen -maxdepthund -mindepth). Ich benutze ./**/anstatt für den **/Fall, dass eines Ihrer Verzeichnisse mit einem beginnt -: Dies verhindert, dass sie als "" angesehen werden

[[ -f "$f"/DONOTDELETE.TXT ]]testet, ob diese Datei existiert und eine Datei ist (wenn Sie möchten, dass sie funktioniert, auch wenn DONOTDELETE.TXT keine Datei ist, verwenden Sie -eanstelle von -f). Genau genommen brauchen Sie das nicht /, da $ f einen abschließenden Schrägstrich enthält, aber ich denke, dass es so besser aussieht und redundante Schrägstriche im Allgemeinen harmlos sind. ||Bedeutet ODER - wenn (und nur wenn) dieser Test falsch ist , wird der Code rechts davon ausgeführt. In diesem Fall werden rm -f "$f"/*alle Dateien mit Ausnahme der versteckten Dateien gelöscht.

Wenn Sie auch versteckte Dateien löschen möchten, können Sie Folgendes verwenden:

for f in ./**/; do [[ -f "$f"/DONOTDELETE.TXT ]] || rm -f "$f"/* "$f"/.*; done
Übelsuppe
quelle