GNU/Linux >> Linux Esercitazione >  >> Linux

Espansione del nome del percorso Bash/shell per Mkdir, Touch Etc?

Quindi fare qualcosa del genere in bash e la maggior parte delle altre shell non funzionerà per creare più sottodirectory o file all'interno di sottodirectory...

mkdir */test
touch */hello.txt

Ovviamente ci sono molti modi per farlo, il mio preferito è usare find quando possibile invece di usare un for loop, principalmente per la leggibilità.

Ma la mia domanda è, perché quanto sopra non funziona?
Da quello che ho capito è perché il file/percorso di destinazione completo non esiste, ma sicuramente è una buona cosa se sto cercando di mkdir o touch . Sono sempre andato avanti e non l'ho mai veramente messo in discussione.
Ma qualcuno ha una spiegazione decente per questo che mi aiuterà a capirlo una volta per tutte?

Risposta accettata:

Il punto che potresti non notare – con cui molte persone hanno problemi,
specialmente se hanno esperienza con altri sistemi operativi prima di arrivare a *nix
– è che, in molti altri sistemi operativi, i caratteri jolly sul riga di comando sono normalmente passati al comando elaborare come meglio crede. Ad esempio, nel prompt dei comandi di Windows

rename *.jpeg *.jpg

Considerando che, in *nix, per semplificare il lavoro
del/i programmatore/i dei singoli comandi (es. mv ), i caratteri jolly
(se non tra virgolette o con caratteri di escape) vengono gestiti dalla shell,
in modo indipendente dall'interfaccia e dalla funzionalità
del comando a cui i caratteri jolly sono argomenti.
La maggior parte dei programmi che accettano nomi di file come argomenti della riga di comando si aspettano che tali file esistano
(sì, mkdir e touch sono eccezioni a questa regola,
così come mkfifo , mknod e, in misura parziale, cp , ln , mv e rename;
e probabilmente ce ne sono altri),
quindi non ha davvero senso che la shell espanda i caratteri jolly
in nomi di file che non esistono.
E per la shell (e, con questo, intendo ogni shell –
Bourne, bash, csh, fish, ksh, zsh, ecc...) gestire le eccezioni in modo diverso
sarebbe probabilmente una seccatura.

Detto questo, ci sono un paio di modi per ottenere un risultato come quello che desideri.
Se sai a cosa si espanderà il carattere jolly,
e non è lungo, puoi generarlo con l'espansione parentesi:

touch {red,orange,yellow,green,blue,indigo,violet}/rgb.txt

Una soluzione più generale:

sh -c 'for arg do mkdir -- "$arg"/test; done' -- *

Gilles mi ha aiutato a trovare un altro modo
per farlo in bash.

benbradley=(*)
mkdir "${benbradley[@]/%//test}"

Ovviamente benbradley è solo un identificatore qui; puoi usare qualsiasi nome
(ad es. qualsiasi singola lettera).
Mi ci sono voluti un paio di tentativi per farlo bene, quindi lasciami scomporre:

  • identifier=value crea una variabile (scalare) denominata identifier (se non esiste già) e assegna il valore value ad esso.
    Ad esempio, G=Man .
    Puoi fare riferimento a una variabile scalare con $identifier;
    ad esempio, $G , o, più sicuro, come ${identifier} .
    Ad esempio, $Gage e $Gilla potrebbe essere indefinito,
    ma ${G}age è Manage e ${G}illa è Manilla .
  • identifier=(value1 value2) crea una variabile array denominata identifier (se non esiste già) e gli assegna i valori elencati.
    Ad esempio,
    spectrum=(red orange yellow green blue indigo violet)

    o

      all_text_files=(*.txt)

      $name farà riferimento al primo elemento (e quindi è abbastanza inutile).
      Puoi fare riferimento a un elemento arbitrario come ${name[subscript]};
      ad esempio, ${spectrum[0]} è red e ${spectrum[4]} è blue .
      E puoi usare ${name[@]} e ${name[*]} per fare riferimento all'intero array.

      Correlati:l'iPod touch è stato rubato e deve essere localizzato?

      Quindi, eccolo a pezzi:

        "   ${   benbradley[@]   /   %   /   /test   }   "
        • ${parameter/pattern/string} espande il ${parameter} e sostituisce la corrispondenza più lunga
          di pattern con string .
        • Se pattern inizia con # ,
          deve corrispondere all'inizio del valore espanso di parameter .
          Se pattern inizia con % ,
          deve corrispondere alla fine del valore espanso di parameter .
          In altre parole,
          %(the-rest_of_the_pattern)

          si comporta come

            (the-rest_of_the_regex)$

            (sì, sembra un po' indietro).
            Quindi un pattern questo è solo un % è come un'espressione regolare che è solo un $
            corrisponde alla fine della stringa di input (spazio di ricerca).

            • E sto usando una string di /test .
              Quindi questo sostituisce la fine del parametro con /test (ovvero, aggiunge /test al parametro).
            • Un'altra cosa su ${parameter/pattern/string} non è intuitivo è che sempre termina con un } .
              Non è necessario e non può , termina con un terzo / .
              Pertanto, un / in string non può essere interpretato come un delimitatore,
              e quindi possiamo avere una string di /test senza bisogno di sfuggire al / .
            • Se parameter è una variabile array
              con pedice @ o * ,
              l'operazione di sostituzione viene applicata a turno a ciascun membro dell'array.
            • Quando fai riferimento a un array come ${name[@]} (anziché ${name[*]} ) e inserisci i risultati tra virgolette,
              mantieni l'integrità degli elementi dell'array
              (ovvero, conservi gli spazi e altri caratteri speciali in essi)
              senza combinare gli elementi separati in una parola lunga.

            Linux
            1. Personalizzazione della shell Bash

            2. Perché l'utente mysql ha la shell bash in /etc/passwd?

            3. 12 Esempi di Bash For Loop per gli script della tua shell Linux

            4. Script bash:utilizzo del comando script da uno script bash per la registrazione di una sessione

            5. Scorciatoia Shell/Bash per la ridenominazione in blocco dei file in una cartella

            Bash For Loop

            .bashrc vs .bash_profile

            Bash Scripting Tutorial per principianti

            Bash Heredoc Tutorial per principianti

            Script di shell per principianti - Come scrivere script Bash in Linux

            Come posso trovare aiuto per il comando punto `.` in *nix?