Verwijder alle bestanden behalve enkele uit een map

Als ik sudo rm -rgebruik, hoe kan ik dan alle bestanden verwijderen, met uitzondering van het volgende:

textfile.txt
backup.tar.gz
script.php
database.sql
info.txt

Antwoord 1, autoriteit 100%

find [path] -type f -not -name 'textfile.txt' -not -name 'backup.tar.gz' -delete

Als u -type fniet opgeeft, zal find ook mappen weergeven, wat u misschien niet wilt.


Of een meer algemene oplossing met behulp van de zeer handige combinatie find | xargs:

find [path] -type f -not -name 'EXPR' -print0 | xargs -0 rm --

verwijder bijvoorbeeld alle niet-txt-bestanden in de huidige map:

find . -type f -not -name '*txt' -print0 | xargs -0 rm --

De combinatie print0en -0is nodig als er spaties zijn in een van de bestandsnamen die moeten worden verwijderd.


Antwoord 2, autoriteit 68%

rm !(textfile.txt|backup.tar.gz|script.php|database.sql|info.txt)

De extglob (Extended Pattern Matching) moet worden ingeschakeld in BASH (als deze niet is ingeschakeld):

shopt -s extglob

Antwoord 3, autoriteit 18%

find . | grep -v "excluded files criteria" | xargs rm

Hiermee worden alle bestanden in de huidige map weergegeven, vervolgens worden alle bestanden weergegeven die niet aan uw criteria voldoen (pas op dat deze overeenkomen met mapnamen) en worden ze vervolgens verwijderd.

Update: als je op basis van je bewerking echt alles uit de huidige map wilt verwijderen, behalve de bestanden die je hebt vermeld, kan dit worden gebruikt:

mkdir /tmp_backup && mv textfile.txt backup.tar.gz script.php database.sql info.txt /tmp_backup/ && rm -r && mv /tmp_backup/* . && rmdir /tmp_backup

Het zal een back-upmap maken /tmp_backup(je hebt root-rechten, toch?), bestanden die je hebt vermeld naar die map verplaatsen, recursief alles in de huidige map verwijderen (je weet dat je’ opnieuw in de juiste map, nietwaar?), ga terug naar de huidige map alles van /tmp_backupen verwijder ten slotte /tmp_backup.

Ik kies de back-upmap in root, want als je probeert om alles recursief uit root te verwijderen, zal je systeem grote problemen hebben.

Er zijn zeker elegantere manieren om dit te doen, maar deze is vrij eenvoudig.


Antwoord 4, autoriteit 10%

Ik gebruik liever een subquerylijst:

rm -r `ls | grep -v "textfile.txt\|backup.tar.gz\|script.php\|database.sql\|info.txt"`

-v, –invert-match selecteer niet-overeenkomende regels

\|Scheidingsteken


Antwoord 5, autoriteit 9%

Ervan uitgaande dat bestanden met die namen op meerdere plaatsen in de directorystructuur voorkomen en u ze allemaal wilt behouden:

find . -type f ! -regex ".*/\(textfile.txt\|backup.tar.gz\|script.php\|database.sql\|info.txt\)" -delete

Antwoord 6, autoriteit 8%

Je kunt de GLOBIGNORE-omgevingsvariabele gebruiken in Bash.

Stel dat je alle bestanden wilt verwijderen behalve php en sql, dan kun je het volgende doen –

export GLOBIGNORE=*.php:*.sql
rm *
export GLOBIGNORE=

Als u GLOBIGNORE op deze manier instelt, worden php en sql genegeerd van jokertekens die worden gebruikt zoals “ls *” of “rm *”. Dus als u “rm *” gebruikt na het instellen van de variabele, worden alleen het txt- en tar.gz-bestand verwijderd.


Antwoord 7, autoriteit 4%

Omdat niemand het noemde:

  • Kopieer de bestanden die u niet wilt verwijderen op een veilige plaats
  • verwijder alle bestanden
  • verplaats de gekopieerde bestanden terug

Antwoord 8, autoriteit 3%

Je kunt hiervoor een for-lus schrijven… %)

for x in *
do
        if [ "$x" != "exclude_criteria" ]
        then
                rm -f $x;
        fi
done;

Antwoord 9, autoriteit 3%

Een beetje laat voor de OP, maar hopelijk nuttig voor iedereen die hier veel later komt via google…

Ik vond het antwoord van @awi en commentaar op -delete van @Jamie Bullock erg nuttig. Een eenvoudig hulpprogramma zodat u dit in verschillende mappen kunt doen, waarbij u elke keer verschillende bestandsnamen/typen negeert met minimaal typen:

rm_behalve (of hoe je het ook wilt noemen)

#!/bin/bash
ignore=""
for fignore in "$@"; do
  ignore=${ignore}"-not -name ${fignore} "
done
find . -type f $ignore -delete

bijv. om alles te verwijderen behalve tekstbestanden en foo.bar:

rm_except *.txt foo.bar 

Vergelijkbaar met @mishunika, maar zonder de if-clausule.


Antwoord 10, autoriteit 2%

Als je zshgebruikt, wat ik ten zeerste aanbeveel.

rm -rf ^file/folder pattern to avoid

Met extended_glob

setopt extended_glob
rm -- ^*.txt
rm -- ^*.(sql|txt)

Antwoord 11, autoriteit 2%

Proberen werkte met:

rm -r !(Applications|"Virtualbox VMs"|Downloads|Documents|Desktop|Public)

maar namen met spaties zijn (zoals altijd) moeilijk. Ook geprobeerd met Virtualbox\ VMsin plaats van de aanhalingstekens. Het verwijdert altijd die map (Virtualbox VMs).


Antwoord 12, autoriteit 2%

Gewoon:

rm $(ls -I "*.txt" ) #Deletes file type except *.txt

Of:

rm $(ls -I "*.txt" -I "*.pdf" ) #Deletes file types except *.txt & *.pdf

Antwoord 13

Maak de bestanden onveranderlijk. Zelfs root mag ze niet verwijderen.

chattr +i textfile.txt backup.tar.gz script.php database.sql info.txt
rm *

Alle andere bestanden zijn verwijderd.
Uiteindelijk kun je ze veranderlijk resetten.

chattr -i *

Antwoord 14

Ik geloof dat je kunt gebruiken

rm -v !(filename)

Behalve de bestandsnaam worden alle andere bestanden in de map verwijderd en zorg ervoor dat u deze gebruikt in


Antwoord 15

Dit is vergelijkbaar met de opmerking van @siwei-shen, maar je hebt de vlag -onodig om meerdere patronen te maken. De vlag -ostaat voor ‘of’

find . -type f -not -name '*ignore1' -o -not -name '*ignore2' | xargs rm


Antwoord 16

U kunt dit doen met twee opdrachtreeksen.
Definieer eerst een array met de naam van de bestanden die u niet wilt uitsluiten:

files=( backup.tar.gz script.php database.sql info.txt )

Loop daarna door alle bestanden in de map die u wilt uitsluiten, controleer of de bestandsnaam in de array staat die u niet wilt uitsluiten; zo niet, verwijder dan het bestand.

for file in *; do
  if [[ ! " ${files[@]} " ~= "$file"  ]];then
    rm "$file"
  fi
done

Antwoord 17

Omdat nog niemand dit heeft genoemd, in één specifiek geval:

OLD_FILES=`echo *`
... create new files ...
rm -r $OLD_FILES

(of gewoon rm $OLD_FILES)

of

OLD_FILES=`ls *`
... create new files ...
rm -r $OLD_FILES

Misschien moet je shopt -s nullglobgebruiken als sommige bestanden er wel of niet zijn:

SET_OLD_NULLGLOB=`shopt -p nullglob`
shopt -s nullglob
FILES=`echo *.sh *.bash`
$SET_OLD_NULLGLOB

zonder nullglob, echo *.sh *.bashkan je “a.sh b.sh *.bash” geven.

(Dat gezegd hebbende, geef ik zelf de voorkeur aan dit antwoord, ook al werkt het niet in OSX)


Antwoord 18

In plaats van een direct commando te gebruiken, verplaats de vereiste bestanden naar de tijdelijke map buiten de huidige map. Verwijder vervolgens alle bestanden met rm *of rm -r *.

Verplaats vervolgens de vereiste bestanden naar de huidige map.


Antwoord 19

Verwijder alles behalve bestandsnaam:

ls -d /path/to/your/files/* |grep -v file.name|xargs rm -rf

Other episodes