Cita un nome file in uno script passato a chmod?

1

Ho difficoltà a citare un nome file che alla fine viene passato a chmod . Lo script è stato originariamente scritto per StrictModes di SSH e authorized_keys , ma ho dovuto espanderlo a causa di un pessimo UMASK che ha causato qualche disagio al filesystem. Lo script è sotto, e sta producendo carichi di:

chmod: /Users/<user>/Library/Application: No such file or directory
chmod: Support/TextMate/Managed/Bundles/HTML.tmbundle/Macros/Delete: No such file or directory
chmod: whitespace: No such file or directory
chmod: between: No such file or directory
chmod: tags.plist: No such file or directory
...
chmod: /Users/<user>/Library/Caches/com.operasoftware.Opera/Media: No such file or directory
chmod: Cache/index: No such file or directory
cut: stdin: Illegal byte sequence
...

Ho provato qualche soluzione alternativa, ma nessuno di loro mi ha aiutato. Ho provato a fare il doppio quoting come ""$file"" , ma il problema persisteva. Ho anche provato i tick posteriori (che in questo caso sono scoraggiati), ma il problema persisteva.

Il più vicino che ho potuto effettivamente citare era il "\"""$file""\"" disfunzionale. Ma poi chmod si è lamentato che il nome file (con virgolette) non era un file reale:

$ sudo ~/fix-perms.sh
chmod: "/Users/Shared/.localized": No such file or directory
chmod: "/Users/<user>/.CFUserTextEncoding": No such file or directory
chmod: "/Users/<user>/.lesshst": No such file or directory

Come cito il nome file che esce da find che viene passato su chmod ? O come ottengo chmod per prendere il nome file come argomento singolo?

$ cat ~/fix-perms.sh 
#!/bin/bash

# Directories
find /Users/* -type d -exec chmod 0700 {} \;
find /Users/Shared -type d -exec chmod 0777 {} \;

# Files
for file in 'find /Users/* -type f';
do
    if [ 'file "$file" | cut -d":" -f 2 | grep -i -c executable' -eq 0 ];
    then
        'chmod 0600 "$file"'
    else
        'chmod 0700 "$file"'
    fi
done

for user in 'ls -A /Users';
do
    if [ -e "/Users/$user/.ssh/authorized_keys" ];
    then
        chmod 0600 "/Users/${user}/.ssh/authorized_keys"
    fi
done
    
posta jww 26.08.2015 - 16:05
fonte

4 risposte

1

Sono stato in grado di risolvere il problema cambiando IFS in IFS=$(echo -en "\n\b") e non citando il nome del file. IFS è Separatore di campo interno , viene utilizzato (tra gli altri) per la divisione delle parole dopo le espansioni della shell e include uno spazio per impostazione predefinita.

Ho trovato il trucco IFS su Shell BASH: per file di loop di nixCraft Nomi con spazi .

$ cat fix-perms.sh
#!/bin/bash

SAVED_IFS=$IFS
IFS=$(echo -en "\n\b")

# Directories
chmod 0755 /Users
find /Users/* -type d -exec chmod 0700 {} \;
find /Users/Shared -type d -exec chmod 0777 {} \;

# Files
for file in 'find /Users/* -type f';
do
    if [ 'file "$file" | cut -d":" -f 2 | grep -i -c executable' -eq 0 ];
    then
        chmod 0600 "$file"
    else
        chmod 0700 "$file"
    fi
done

for user in 'ls -A /Users';
do
    if [ -e "/Users/$user/.ssh/authorized_keys" ];
    then
        chmod 0600 "/Users/${user}/.ssh/authorized_keys"
    fi
done

IFS=$SAVED_IFS
    
risposta data 27.08.2015 - 20:44
fonte
3

fwiw, find [options] -print0 , se usato insieme a (piped to) xargs -0 [options] , gestisce i nomi di file con spazi, senza scherzare con for loops o IFS :

find /Users ! -path '/Users/Shared*' -type f -print0 | xargs -0 -I {} \
    bash -c 'if [[ "$(file -b --mime-type -- "{}")" = "application/x-mach-binary" ]]; then
                 chmod 700 "{}"
             else
                 chmod 600 "{}"
             fi'
    
risposta data 30.08.2015 - 16:04
fonte
1

find può gestire spazi nei nomi di file. Il tuo for loops sta causando i problemi. Puoi inserire la logica in più comandi find . Non tutte le directory nella cartella home di un utente dovrebbero essere accessibili solo a se stesse. Pubblico e Siti vengono in mente. Puoi sistemarli separatamente in un altro comando di ricerca.

find /Users/* ! -path '/Users/Shared*'  -type d ! \( -name Public -o -name Sites \) -exec chmod 0700 {} +

Il comando esclude la directory condivisa insieme alle directory pubbliche e di Sites, quindi modifica le autorizzazioni sulle restanti directory.

Puoi utilizzare + nelle tue dichiarazioni find per fare in modo che find agisca come se fosse xargs .

find /Users/Shared -type d -exec chmod 0777 {} +

Supponendo che i file eseguibili nella cartella home di un utente siano pacchetti di applicazioni, puoi farlo.

find /Users/* ! -path '/Users/Shared*' type f ! perm -755 -exec chmod 0600 {} +
    
risposta data 26.08.2015 - 18:19
fonte
1
La soluzione

mtklr's (e Patrix ') funzionerà, ma trovo che sia più semplice utilizzare un ciclo while read quando si ha a che fare con un elenco di file da find ... -print0 :

find /Users '!' -path '/Users/Shared*' -type f -print0 |
    while IFS= read -d '' -r file; do
        if file "$file" | grep -iq ": .*executable"; then
            chmod 700 "$file"
        else
            chmod 600 "$file"
        fi
    done

read -d '' utilizza null come delimitatore. Ho anche usato -r per impedire che provi ad analizzare gli escape e IFS= per impedirgli di tagliare gli spazi bianchi alla fine del nome del file (e dato che è un prefisso al comando read , si applica solo a quello e non è necessario reimpostarlo in seguito).

BTW, ho anche usato if ... | grep -q ... - il -q dice grep di non mostrare nulla, ma il suo stato di uscita avrà successo solo se trova almeno una corrispondenza. E poiché if verifica solo lo stato di uscita del comando in esso, è tutto ciò che è necessario.

BTW, questo è principalmente basato su BashFAQ # 20: Come posso trovare e gestire in sicurezza i nomi dei file che contengono newline, spazi o entrambi? . Ti consiglio di dargli un'occhiata ...

    
risposta data 31.08.2015 - 04:18
fonte

Leggi altre domande sui tag