Come posso elencare i file di cui non esistono collegamenti simbolici?


10

Ho una grande directory "myfiles" piena di documenti vari e non voglio modificarne la struttura.

Ho quindi creato (diverse) altre directory per ogni classe di documenti. Ad esempio, ho una directory "images" che contiene collegamenti simbolici a ciascuno .jpgo .cr2file nella directory "myfiles" più altri file descrittivi per ciascun collegamento simbolico (con lo stesso nome file) con descrizione e altri metadati. I collegamenti simbolici nella directory / images potrebbero avere un nome diverso dal file collegato originale.

Sto cercando di trovare il modo più semplice per assicurarmi che ogni singolo file di immagine nella directory "myfiles" abbia un link simbolico nella directory "images".

Vedi un esempio della struttura delle cartelle

/myfiles/a.doc
/myfiles/b.jpg
/myfiles/c.cr2
/myfiles/d.mov

dovrebbe risultare

/images/b_800x600.jpg
/images/b_800x600.desc
/images/c_3820x5640.cr2
/images/c_3820x5640.cr2

Non è una risposta completa, ma è possibile salvare i risultati di a find /myfiles -type fin un file, quindi utilizzare find /images -type l -exec readlink {} \; | egrep myfilesper ottenere un elenco di file con collegamento simbolico, /imagesquindi scorrere i risultati facendo uno sedsu ciascuno per eliminare i percorsi nel primo file salvato poiché già avere il link simbolico e i file rimasti sono i file che non hanno il link simbolico.
Bratchley,

2
È possibile utilizzare invece i collegamenti fisici, quindi è possibile utilizzare il contatore dei collegamenti fisici per vedere se si dispone di collegamenti? Usando ls -lpuoi vedere il conteggio degli hardlink nella seconda colonna.
Lambert,

Fai quello che dice @Lambert. rmquelle dir di symlink e usate pax -rwl -s "\|.*regex|modifes_filename|" /path/to/myfiles/*.jpg /path/to/jpg_dirad esempio per ottenere hardlink con nomi di file modificati a livello di programmazione solo per quei file che corrispondono ai tuoi jpg. Puoi ricavarne molto di più - come il raggruppamento in base ai tempi di cambio ecc.
mikeserv

Risposte:


6

Se ho sottovalutato correttamente la domanda, hai bisogno di file in myfile che non abbiano collegamenti simbolici nelle immagini:

#!/bin/bash

OIFS="$IFS"
IFS=$'\n'

files="$(find myfiles/ -type f -name '*.jpg' -or -name '*.cr2')"
for f in $files; do
    list="$(find -L images/ -xtype l -samefile "$f")"
    if [[ "$list" == "" ]]; then
        echo "$f does not have symlink."
    fi
done

IFS="$OIFS"

Esiste un avvertimento con questo approccio se si dispone del file a.jpg nella directory myfiles / 1 e si dispone di un collegamento simbolico a quel file nella directory images / 3 o semplicemente nelle immagini / il file non verrà riportato con il collegamento simbolico mancante.


Grazie ! Sì, hai capito bene. Chiudi ma non del tutto. Colpa mia no tua :-) L'esempio che ho dato mostra una semplicistica directory myfiles. In realtà i file di immagine sotto myfile possono trovarsi all'interno di qualsiasi livello arbitrario di directory nidificate.
Robert Alexander,

Ho modificato la risposta per cercare in interi file personali, ma controlla se questo è ciò che desideri.
Taliezin,

QUASI lì :-) Il tuo script si singhiozza quando i file hanno spazi (e forse altre cazzate come singoli apostrofi "in loro ...
Robert Alexander

Penso che ora dovrebbe essere ok
taliezin

L'ultima modifica divide ogni f al verificarsi di ogni lettera n! :-) Ho agganciato la linea IFS a IFS = quindi una nuova riga dalla tastiera e poi un'altra ". Ora la divisione sembra funzionare ma ottengo una lunga sequenza di" missinglink.sh: 11: missinglinks.sh: [[: not found "
Robert Alexander

3

Presumo che i file sotto myfilesnon siano collegamenti simbolici e che nessuno dei nomi dei file contenga righe. (Il mio approccio può ancora funzionare se queste assunzioni vengono violate ma diventa più complicato.) Suppongo anche che tu abbia l' readlinkutilità comune e che supporti la -fcanonicalizzazione dei percorsi, come nel caso di Linux (sia GNU che BusyBox), ma non ad es. OSX.

Crea un elenco di file e ordinalo per una buona misura:

find /myfiles -type f -print | sort >all.list

Crea un elenco di target di link simbolici, con percorsi assoluti.

find /images -type f -exec readlink -f {} \; | sort >linked.list

Elenca i file che non sono collegati:

comm -32 all.list linked.list

Se usi una shell che supporta la sostituzione di processo, puoi metterlo tutto in un solo comando:

comm -23 <(find /myfiles -type f -print | sort) \
         <(find /images -type f -exec readlink -f {} \; | sort)

Se i collegamenti /imagesindicati sono assoluti, è possibile utilizzare readlinksenza l' -fopzione, disponibile in * BSD e OSX.


Stavo per pubblicare qualcosa come il tuo commcomando, ma ora non vedrò che l'hai già fatto. Tuttavia, il reindirizzamento da sortnon ha senso; quindi le sostituzioni di processo non produrranno nulla. Inoltre, è possibile aggiungere molte directory accanto /imagesse si desidera trovare file in /myfilescui non siano presenti collegamenti simbolici a una delle numerose directory diverse /images.
Tripleee,

1
Vedi stackoverflow.com/questions/7665/… per alternative areadlink -f
tripleee

@tripleee Ho dimenticato di eliminare il reindirizzamento quando ho creato la versione di reindirizzamento del processo, grazie. Sì, è possibile aggiungere facilmente altre directory o apportare altre varianti.
Gilles 'SO- smetti di essere malvagio' il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.