GNU/Linux >> Linux Esercitazione >  >> Linux

Escape caratteri sconosciuti dalla stringa per -exec?

Ho un comando di ricerca che trova determinati file e directory. Il comando find esegue quindi rsync con i file e le directory trovati in precedenza come origine. Il problema è che quei file e directory possono avere tutti i tipi di caratteri come virgolette singole e doppie per non parlare dei caratteri illegali di Windows ecc...

Come posso eseguire l'escape dinamico di una stringa da utilizzare in rsync o altri comandi?

Questo comando funziona codificando a fondo le virgolette doppie per la stringa sorgente rsync, ma si interromperà se la stringa contiene virgolette doppie.

find "/mnt/downloads/cache/" -depth -mindepth 1 \( \
-type f \! -exec fuser -s '{}' \; -o \
-type d \! -empty \) \
\( -exec echo rsync -i -dIWRpEAXogt --numeric-ids --inplace --dry-run '"{}"' "${POOL}" \; \)

output risultante:

rsync -i -dIWRpEAXogt --numeric-ids --inplace --dry-run "test/this " is an issue" /mnt/backing

Comando di lavoro dopo le informazioni nelle risposte applicate:

find "/mnt/downloads/cache/" -depth -mindepth 1 \( \
                             -type f \! -exec fuser -s {} \; -o \
                             -type d \! -empty \) \
                             \( -exec rsync -i -dIWRpEAXogt --remove-source-files-- "${POOL} \; \) \
                             -o \( -type d -empty -exec rm -d {} \; \)

Risposta accettata:

Il tuo problema di quotazione viene da te che cerchi di risolvere un problema che non hai. La necessità di citare gli argomenti entra in gioco solo quando hai a che fare con una shell e se find sta chiamando rsync direttamente, non è coinvolta alcuna shell. L'uso dell'output visivo non è un buon modo per sapere se funziona o meno perché non puoi vedere dove inizia e dove finisce ogni argomento.

Ecco cosa intendo:

# touch "foo'\"bar"

# ls
foo'"bar

# find . -type f -exec stat {} \;
  File: ‘./foo'"bar’
  Size: 0           Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d    Inode: 1659137     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1004/ phemmer)   Gid: ( 1004/ phemmer)
Access: 2017-12-09 13:21:28.742597483 -0500
Modify: 2017-12-09 13:21:28.742597483 -0500
Change: 2017-12-09 13:21:28.742597483 -0500
 Birth: -

Nota che non ho citato il {} nell'arg a stat .

Detto questo, il tuo comando sarà molto poco performante, perché stai chiamando rsync per ogni singolo file corrispondente. Ci sono 2 modi per risolverlo.

Come altri hanno indicato, puoi usare pipe l'elenco dei file su rsync su stdin:

# find . -type f -print0 | rsync --files-from=- -0 . dest/

# ls dest/
foo'"bar

Questo utilizzerà i byte nulli come delimitatore del nome del file poiché i file non possono contenere byte nulli nel loro nome.

Correlati:come correggere l'errore "Il dispositivo USB sconosciuto ha bisogno di più energia di quella che la porta può fornire"?

Se stai usando GNU find , hai un altro metodo per invocare -exec , e questo è -exec {} + . In questo stile find passerà più di un argomento alla volta. Tuttavia, tutti gli argomenti vengono aggiunti alla fine del comando, non nel mezzo. Puoi risolvere questo problema passando gli argomenti attraverso una piccola shell:

# find . -type f -exec sh -c 'rsync "[email protected]" dest/' {} +

# ls dest/
foo'"bar

Questo passerà l'elenco dei file a sh che li sostituirà con "[email protected]"


Linux
  1. Cosa rappresentano i personaggi speciali in Echo {a..z}?

  2. Ottenere l'opzione -exec in Trova per funzionare?

  3. Rompere la ricerca se un -exec fallisce?

  4. Profondità massima equivalente per Find in Aix?

  5. Manipola {} Restituisce la stringa da Find -exec?

Come trovare una stringa in un file su Linux

Come cercare file dalla riga di comando di Linux

Come rimuovere (^M) caratteri da un file in Linux

Come trovare il percorso completo del programma C++ Linux dall'interno?

Rimuovi tutti i caratteri speciali e le maiuscole dalla stringa in bash

grep per trovare i file che contengono una stringa lunga più di x caratteri?