GNU/Linux >> Znalost Linux >  >> Linux

Je možné bezpečně použít `find -exec Sh -c`?

Snažím se použít find na echo 0 do některých souborů, ale zřejmě to funguje pouze s sh -c :

find /proc/sys/net/ipv6 -name accept_ra -exec sh -c 'echo 0 > {}' ;

Ale pomocí sh -c pomocí find -exec cítím se velmi neklidně, protože mám podezření na problémy s citováním. Trochu jsem si s tím pohrál a zřejmě mé podezření bylo oprávněné:

  • Moje testovací nastavení:

    [email protected] ~ % cd findtest 
    [email protected] ~/findtest % echo one > file with spaces
    [email protected] ~/findtest % echo two > file with 'single quotes'
    [email protected] ~/findtest % echo three > file with "double quotes"
    [email protected] ~/findtest % ll
    insgesamt 12K
    -rw-rw-r-- 1 martin martin 6 Sep 17 12:01 file with "double quotes"
    -rw-rw-r-- 1 martin martin 4 Sep 17 12:01 file with 'single quotes'
    -rw-rw-r-- 1 martin martin 4 Sep 17 12:01 file with spaces
    
  • Pomocí find -exec bez sh -c Zdá se, že funguje bez problémů – zde není třeba citovat:

    [email protected] ~ % find findtest -type f -exec cat {} ;
    one
    two
    three
    
  • Ale když používám sh -c {} Zdá se, že vyžaduje nějaký druh citace:

    [email protected] ~ % LANG=C find findtest -type f -exec sh -c 'cat {}' ;
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: spaces: No such file or directory
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: single quotes: No such file or directory
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: double quotes: No such file or directory
    
  • Dvojité uvozovky fungují, pokud žádný název souboru neobsahuje uvozovky:

    [email protected] ~ % LANG=C find findtest -type f -exec sh -c 'cat "{}"' ;
    one
    two
    cat: findtest/file with double: No such file or directory
    cat: quotes: No such file or directory
    
  • Jednoduché uvozovky fungují, pokud žádný název souboru neobsahuje jednoduché uvozovky:

    [email protected] ~ % LANG=C find findtest -type f -exec sh -c "cat '{}'" ;
    one
    cat: findtest/file with single: No such file or directory
    cat: quotes: No such file or directory
    three
    

Nenašel jsem řešení, které by fungovalo ve všech případech. Je něco, co přehlížím, nebo používám sh -c v find -exec ze své podstaty nebezpečné?

Přijatá odpověď:

Nikdy nevkládejte {} v kódu shellu! To vytváří zranitelnost příkazového vkládání. Všimněte si, že pro cat "{}" , není to jen o " znaků, , ` , $ jsou také problémem (uvažte například soubor s názvem ./$(reboot)/accept_ra )¹.

Zde byste chtěli předat názvy souborů jako samostatné argumenty do sh (není v kódu argument) a sh vložený skript (kód argument), abyste na ně odkazovali pomocí pozičních parametrů:

find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} ;

Nebo, abyste se vyhnuli spuštění jednoho sh na soubor:

find . -name accept_ra -exec sh -c 'for file do
  echo 0 > "$file"; done' sh {} +

Totéž platí pro xargs -I{} nebo zsh 's zargs -I{} . Nepište:

Související:Linux – ekvivalent linuxu Macu „Shake to Find Cursor“?

<list.txt xargs -I{} sh -c 'cmd > {}'

Což by byla zranitelnost vkládání příkazů stejným způsobem jako u find výše, ale:

<list.txt xargs sh -c 'for file do cmd > "$file"; done' sh

Což má také tu výhodu, že se vyhnete spuštění jednoho sh na soubor a chyba při list.txt neobsahuje žádný soubor.

Pomocí zsh 's zargs , pravděpodobně budete chtít použít funkci místo volání sh -c :

do-it() cmd > $1
zargs ./*.txt -- do-it

Všimněte si, že ve všech příkladech výše je druhý sh výše přejde do $0 vloženého skriptu . Měli byste tam použít něco relevantního (například sh nebo find-sh ), ne věci jako _ , - , -- nebo prázdný řetězec jako hodnotu v $0 se používá pro chybové zprávy shellu:

$ find . -name accept_ra -exec sh -c 'echo 0 > "$1"' inline-sh {} ;
inline-sh: ./accept_ra: Permission denied

GNU parallel funguje jinak. S ním ne chcete použít sh -c jako parallel již spouští shell a pokouší se nahradit {} s argumentem citovaným ve správné syntaxi pro shell.

<list.txt PARALLEL_SHELL=sh parallel 'cmd > {}'


Linux
  1. Jak používat autofs k připojení sdílených složek NFS

  2. V Linuxu je možné použít .dll

  3. Je možné použít / v názvu souboru?

  1. Použít _roff k podtržení slov?

  2. Jak použít chmod ke změně oprávnění k souboru?

  3. Proč používat shm_open?

  1. Proč na Linuxu používám exa místo ls

  2. Jak používat příkaz Tar v Linuxu

  3. Jak používat typ souboru ve Vimu?