GNU/Linux >> Znalost Linux >  >> Linux

Uniknout neznámým znakům z řetězce pro -exec?

Mám příkaz find, který najde určité soubory a adresáře. Tento příkaz find poté spustí rsync se soubory a adresáři nalezenými dříve jako zdroj. Problém je v tom, že tyto soubory a adresáře mohou mít nejrůznější znaky, jako jsou jednoduché a dvojité uvozovky, nemluvě o nelegálních znacích z Windows atd…

Jak mohu dynamicky escapovat řetězec pro použití v rsync nebo jiných příkazech?

Tento příkaz funguje tak, že pevně zakóduje dvojité uvozovky pro zdrojový řetězec rsync, ale přeruší se, pokud řetězec obsahuje dvojité uvozovky.

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

výsledný výstup:

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

Pracovní příkaz po použití informací v odpovědích:

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

Přijatá odpověď:

Váš problém s citováním pochází z toho, že se snažíte vyřešit problém, který nemáte. Potřeba citovat argumenty přichází do hry pouze tehdy, když máte co do činění s shellem a pokud find volá rsync přímo, není zapojen žádný shell. Použití vizuálního výstupu není dobrý způsob, jak zjistit, zda funguje nebo ne, protože nevidíte, kde každý argument začíná a končí.

Zde je to, co mám na mysli:

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

Všimněte si, že jsem necitoval {} v argumentu stat .

Nyní, když bylo řečeno, váš příkaz bude velmi nevýkonný, protože voláte rsync pro každý odpovídající soubor. Existují 2 způsoby, jak to můžete vyřešit.

Jak uvedli jiní, můžete použít kanál se seznamem souborů k rsync na stdin:

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

# ls dest/
foo'"bar

Tím se jako oddělovač názvu souboru použijí prázdné bajty, protože soubory nemohou ve svém názvu obsahovat prázdné bajty.

Související:Jak opravit chybu „Neznámé zařízení USB potřebuje více energie, než může port dodat“?

Pokud používáte GNU, find , máte jiný způsob vyvolání -exec a to je -exec {} + . V tomto stylu find projde více než jedním argumentem najednou. Všechny argumenty se však přidávají na konec příkazu, nikoli doprostřed. Můžete to vyřešit předáním argumentů přes malý shell:

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

# ls dest/
foo'"bar

Tím předáte seznam souborů do sh které je poté nahradí za "[email protected]"


Linux
  1. Shell Test najít vzor v řetězci?

  2. Najít -exec + Vs Najít | Xargs:Který si vybrat?

  3. Příkaz pro tisk pouze posledních 3 znaků řetězce?

  1. Jak najít úplnou cestu k programu C++ Linux zevnitř?

  2. Řetězec potrubí do GNU Datum pro konverzi - jak to udělat, aby četl ze stdin?

  3. grep najít soubory, které obsahují řetězec delší než x znaků?

  1. Tr Analog pro znaky Unicode?

  2. Co znamenají speciální postavy v Echo {a..z}?

  3. příkaz najít z PID