O que esta linha de comando (`echo $1 | xargs -n 1 basename | cut -d '.' -f1`) faz?

O que esta linha de comando (`echo $1 | xargs -n 1 basename | cut -d '.' -f1`) faz?

Eu preciso entender esta linha de comando:

file=`echo $1 | xargs -n 1 basename | cut -d '.' -f1`

Responder1

Ele atribui um pouco de nome de arquivo (possivelmente com um caminho) à variável file. Especificamente, o bit antes do primeiro .caractere no nome do próprio arquivo. Em outras palavras, é preciso algo parecido /some/path/hello.worlde analisa a helloparte.

Uma dica seria executar cada parte do pipeline na linha de comando:

$ thing="/some/path/hello.world"

$ echo "$thing"
/some/path/hello.world

$ echo "$thing" | xargs -n 1 basename
hello.world

$ echo "$thing" | xargs -n 1 basename | cut -d '.' -f 1
hello

Os crases são usados ​​para retornar a saída do pipeline e atribuí-la a file. Este $1é o primeiro argumento na linha de comando (para qualquer script ou função shell da qual faz parte).

É provável que a única razão pela qual xargs -n 1 basenameseja usado em vez de simples basenameseja porque o basenameutilitário não lê a entrada padrão, mas xargso faz.

Uma versão mais curta (e mais rápida) da mesma coisa seria bashou ksh93seria

file=${1##*/}
file=${file%%.*}

Responder2

A linha extrai os nomes dos arquivos sem extensões dos caminhos fornecidos via $1(o primeiro argumento do script em que essa linha aparece). O resultado é salvo na variável file.

Demonstração:

$ echo /etc/dhcpcd.conf ../foo/bar/filename.tar.gz | xargs -n 1 basename | cut -d '.' -f1
dhcpcd
filename

Responder3

A combinação de echoe xargsé bastante curiosa aqui.

basenamepega um nome de caminho na linha de comando e gera o componente final dele (ou seja, parte após a última barra, geralmente). xargsapenas coloca as palavras lidas de sua entrada (o pipe) na linha de comando daqui basename. Então por que não apenas usar basename $1?

Há, no entanto, uma diferença.

Se echo $1 | xargs -n 1 basenameo parâmetro $1contiver espaços em branco, xargsirá dividi-lo em espaços e chamar basenamecada palavra separadamente. O resultado final será que uma parte do nome do arquivo será escolhida paratodosas palavras, comoArmínio mostrou.

A outra opção, basename $1, chamaria basenameapenas uma vez (e falharia de algumas maneiras interessantes devido à divisão de palavras).

Se o comando deveria lidar apenas com um nome de arquivo, seria melhor escrito como:

file=$(basename "$1" | cut -d '.' -f 1)

Com as citações. (ou usando a expansão do shell de remoção de sufixos ${file%%.*}em vez do cutasKusalananda mostrou.)

Se, por outro lado, for necessário lidar com vários nomes de arquivos, pode ser mais limpo passá-los usando um array ou nos parâmetros posicionais (todos eles, não apenas $1).

Responder4

A linha armazena o nome de um arquivo, sem extensão e caminho, na variável $file.

Em detalhe:

echo $1imprime o primeiro argumento da linha de comando passado para o script, xargs -n 1 basenamepassa a string ecoada como argumentos para o comando basename, que retira o caminho do nome do arquivo. cut -d '.' -f1remove a extensão.

Então, por exemplo, se você executar

echo directory/test.sh | xargs -n 1 basename | cut -d '.' -f1

o resultado (salvo em $file) será test.

informação relacionada