GNU/Linux >> Tutoriels Linux >  >> Linux

Échapper les caractères inconnus de la chaîne pour -exec ?

J'ai une commande find qui trouve certains fichiers et répertoires. Cette commande find exécute ensuite rsync avec les fichiers et répertoires trouvés précédemment comme source. Le problème est que ces fichiers et répertoires peuvent contenir toutes sortes de caractères tels que des guillemets simples et doubles, sans parler des caractères illégaux de Windows, etc…

Comment puis-je échapper dynamiquement une chaîne à utiliser dans rsync ou d'autres commandes ?

Cette commande fonctionne en codant en dur des guillemets doubles pour la chaîne source rsync, mais elle se cassera si la chaîne contient des guillemets doubles.

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}" \; \)

sortie résultante :

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

Commande de travail après l'application des informations dans les réponses :

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 {} \; \)

Réponse acceptée :

Votre problème de devis vient du fait que vous essayez de résoudre un problème que vous n'avez pas. Le besoin de citer des arguments n'entre en jeu que lorsque vous avez affaire à un shell, et si find appelle rsync directement, il n'y a pas de shell impliqué. L'utilisation de la sortie visuelle n'est pas un bon moyen de savoir si cela fonctionne ou non, car vous ne pouvez pas voir où commence et se termine chaque argument.

Voici ce que je veux dire :

# 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: -

Notez que je n'ai pas cité le {} dans l'argument de stat .

Cela dit, votre commande va être très peu performante, car vous appelez rsync pour chaque fichier correspondant. Il existe 2 façons de résoudre ce problème.

Comme d'autres l'ont indiqué, vous pouvez utiliser le canal de la liste de fichiers vers rsync sur stdin :

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

# ls dest/
foo'"bar

Cela utilisera des octets nuls comme délimiteur de nom de fichier puisque les fichiers ne peuvent pas contenir d'octets nuls dans leur nom.

Connexe :Comment corriger l'erreur « Le périphérique USB inconnu a besoin de plus d'énergie que le port ne peut en fournir » ?

Si vous utilisez GNU find , vous avez une autre méthode pour invoquer -exec , et c'est -exec {} + . Dans ce style find passera plus d'un argument à la fois. Cependant tous les arguments sont ajoutés à la fin de la commande, pas au milieu. Vous pouvez résoudre ce problème en passant les arguments via un petit shell :

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

# ls dest/
foo'"bar

Cela passera la liste des fichiers au sh qui les substituera ensuite au "[email protected]"


Linux
  1. Tr analogique pour les caractères Unicode ?

  2. Que signifient les caractères spéciaux dans Echo {a..z} ?

  3. Obtenir l'option -exec dans Find To Work ?

  4. Sortir de la recherche si un -exec échoue ?

  5. Maxdepth équivalent pour Find In Aix ?

Comment trouver une chaîne dans un fichier sous Linux

Comment rechercher des fichiers à partir de la ligne de commande Linux

Comment supprimer les caractères (^M) d'un fichier sous Linux

Supprimez tous les caractères spéciaux et la casse de la chaîne dans bash

comment rechercher un répertoire à partir du terminal dans ubuntu

trouver la commande du PID