2010-05-06 13 views
17

Tengo un archivo de manifiesto que es solo una lista de nombres de archivo separados por nueva línea. ¿Cómo puedo eliminar todos los archivos que son no nombrados en el manifiesto desde una carpeta?BASH: ¿Cómo eliminar todos los archivos excepto aquellos nombrados en un manifiesto?

He intentado construir un comando find ./ ! -name "filename" dinámicamente:

command="find ./ ! -name \"MANIFEST\" " 
for line in `cat MANIFEST`; do 
    command=${command}"! -name \"${line}\" " 
done 
command=${command} -exec echo {} \; 
$command 

pero se mantienen los archivos.

[Nota:] Sé que esto usa eco. Quiero comprobar lo que hace mi comando antes de usarlo.

Solución: (gracias PixelBeat)

ls -1 > ALLFILES 
sort MANIFEST MANIFEST ALLFILES | uniq -u | xargs rm 

Sin archivo temporal:

ls -1 | sort MANIFEST MANIFEST - | uniq -u | xargs rm 

Tanto Ignora si los archivos están ordenados/No.

+0

Thanks All! Lo estoy dando a pixelbeat para su guía de shell que contenía la solución – brice

Respuesta

11

Utilizando el patrón de "establecer la diferencia" de http://www.pixelbeat.org/cmdline.html#sets

(find ./ -type f -printf "%P\n"; cat MANIFEST MANIFEST; echo MANIFEST) | 
    sort | uniq -u | xargs -r rm 

Nota enumero MANIFIESTO dos veces en caso de que haya archivos que aparecen allí que no están realmente presentes. También tenga en cuenta lo anterior es compatible con archivos en los subdirectorios

+0

Obtuve 'rm: missing operand' en tu comando. Lo descubrí usando ls, comm y xargs. Gracias de todos modos pb – brice

+0

Añadir un -r para xargs para eliminar esa advertencia (cuando no se necesitan archivos que desea borrar) – pixelbeat

+1

Set patrón de diferencia usando 'grep' lugar: ' find ./ type f -printf "% P \ n "| fgrep -vf MANIFEST | ... ' –

3

lo descubrió:

ls -1 > ALLFILES 
comm -3 MANIFEST ALLFILES | xargs rm 
+2

Sí comm -3 es equivalente a mi solución anterior. Pero tenga cuidado ya que la comunicación espera entradas ya ordenadas – pixelbeat

+0

Saludos, encendidas utilizando la diferencia establecida de desordenado. – brice

+1

Use 'xargs -L 1' si sus nombres de archivo contienen espacios. – djjeck

0

asume que ya está ordenada MANIFIESTO:

find -type f -printf %P\\n | sort | comm -3 MANIFEST - | xargs rm 
1

Sólo por diversión, un Perl-1 forro ... realmente no es necesario en este caso pero mucho más personalizable/extensible que Bash si quieres algo más elegante :)

$ ls 
1 2 3 4 5 M 
$ cat M 
1 
3 
$ perl -e '{use File::Slurp; %M = map {chomp; $_ => 1} read_file("M"); $M{M}=1; \ 
foreach $f (glob("*")) {next if $M{$f}; unlink "$f"||die "Can not unlink: $!\n" };}' 
$ ls 
1 3 M 

Lo anterior puede ser aún más corto si se pasa el manifiesto de la entrada estándar

perl -e '{%M = map {chomp; $_ => 1} <>; $M{M}=1; \ 
foreach $f (glob("*")) {next if $M{$f};unlink "$f"||die "Can not unlink: $!\n" };}' M 
13

Para cada archivoen el directorio actual grep nombre de archivo en el archivo de manifiesto y rm archivo si no es igualada.

for file in * 
    do grep -q -F "$file" PATH_TO_YOUR_MANIFIST || rm "$file" 
done 
+1

Si usa este método, asegúrese de agregar el nombre de su archivo de manifiesto al manifiesto en caso de que lo coloque en el mismo directorio donde está eliminando los archivos. Si coloca este código en una secuencia de comandos, también agregue el nombre de esa secuencia de comandos al manifiesto. –

Cuestiones relacionadas