Como obter a primeira palavra de uma string?

43

Quando 'echo *' recebo a seguinte saída:

file1 file2 file3 ...

O que eu quero é escolher a primeira palavra. Como posso proceder?

vdegenne
fonte
1
A utilização de @mattdm lsnão funcionará se um dos nomes de arquivos contiver um espaço em branco.
Helpermethod
2
Como você define a palavra ? Se o primeiro arquivo for Sunset on a beach.jpg, deveria ser Sunsetou o nome completo do arquivo? Que tal Sea, sex and sun.ogg? Sea, Sea,Ou a totalidade nome do arquivo?
Stéphane Chazelas 21/03
O @mattdm ls | head -1me fornece coisas aleatórias, como a.patch p.pyqual não é a primeira palavra e nem mesmo os arquivos em ordem alfabética.
phuclv

Respostas:

52

Você pode passar pelo awk e fazer ecoar a primeira palavra

echo * | head -n1 | awk '{print $1;}'

ou você corta a corda e seleciona a primeira palavra:

echo *  | head -n1 | cut -d " " -f1

ou você o enche através de sed e manda remover tudo, menos a primeira palavra

echo * | head -n1 | sed -e 's/\s.*$//'

Adicionado o | head -n1para satisfazer nitpickers. Caso sua sequência contenha novas linhas | head -n1, a primeira linha será selecionada antes que os comandos importantes selecionem a primeira palavra da sequência passada para ela.

Bananguin
fonte
1
O retornaria a primeira palavra de cada linha, não a primeira palavra.
Stéphane Chazelas
2
Pergunto-me quantas linhas echo *gera
Bananguin
Isso depende de quantos arquivos têm caracteres de nova linha em seu nome ou dependendo do ambiente ou de como o bash foi compilado ou se algum arquivo chamado -eou -ee... aparece na lista, quantas vezes \naparece em um nome de arquivo. Se há um arquivo chamado -n, ele pode até não retornar qualquer linha em tudo ...
Stéphane Chazelas
Bem, ainda estamos falando do bash e 1. geralmente o bash não passa uma string com novas linhas como uma string com novas linhas 2. é muito difícil e incomum (impossível?) Ter uma nova linha em um nome de arquivo 3. a \ n in um nome de arquivo será exibido como \ n 4. 3 válido para nomes de arquivos começando com - 5. mesmo quando chamado com -n ou -e echo abrirá o stdout e o fechará quando terminar, é claro que retornará uma linha e, em menos seqüência de um, para que o assunto 6. i editado o meu conselho para pelo menos cuidar do problema de múltiplas linhas
Bananguin
1
Todos os 5 pontos são falsos. Tente em um diretório vazio: touch '$a\nb' 'a\nb'; env BASHOPTS=xpg_echo bash -c 'echo * | wc -l'( xpg_echoé ativado sempre que bashfor necessário ser compatível com Unix). E em outro diretório vazio: touch ./-n; bash -c 'echo * | wc -l'. Uma linha é uma sequência de caracteres terminados por um caractere de nova linha. Se echonão gera um caractere de nova linha, não gera nenhuma linha. O comportamento de utilitários de texto como cut, awkou sednão é especificado, se a entrada tiver caracteres extras após o último caractere de nova linha e o comportamento variar entre as implementações.
Stéphane Chazelas
18

Assumindo um shell posixy ( /bin/shou /bin/bashpode fazer isso)

all=$(echo *)
first=${all%% *}

A construção ${all%% *}é um exemplo de remoção de substring . Os %%meios excluem a correspondência mais longa de *(um espaço seguido por qualquer coisa) da extremidade direita da variável all. Você pode ler mais sobre manipulação de strings aqui .

Esta solução assume que o separador é um espaço. Se você estiver fazendo isso com nomes de arquivos, qualquer um com espaços o quebrará.

starfry
fonte
Agradável. Mas eu gostei do simples e outra versão mais não-hacky com headecut
Anwar
4
OMI, cabeça, corte e sed são menos simples. Por que gerar outra ferramenta quando a substituição de parâmetro integrada faz o trabalho com eficiência. Essa resposta é a maneira mais eficiente e portátil de selecionar a primeira palavra de uma lista de palavras separadas por espaço (que é todo o OP solicitado).
Juan
7

Supondo que você realmente deseja o primeiro nome do arquivo e não a primeira palavra , aqui está uma maneira que não quebra no espaço em branco:

shopt -s nullglob
files=(*)
printf '%s\n' "${files[0]}"
Chris Down
fonte
1
A primeira palavra também seria fácil:files=($(echo *))
Hauke ​​Laging 24/02
2
Ele quebraria "-n", "-e", "-ne", "-Enenene" ... e, dependendo de como bashfoi compilado ou do ambiente, possivelmente com caracteres de barra invertida.
Stéphane Chazelas
2
@HaukeLaging, você precisará desativar o globbing. Como text=$(echo *); set -f; files=($text):, caso contrário, mais curingas poderiam ser expandidos.
Stéphane Chazelas
3
efiles=$(echo *); echo ${files%% *}
vdegenne 27/02
1
@memnoch_proxy Ele quebrará nomes de arquivos que contenham espaços em branco, use-o com cautela.
22413 Chris Down
5

Você pode usar os parâmetros posicionais

set -- *
echo "$1"
Glenn Jackman
fonte
3
Esteja ciente de que isso destruirá quaisquer outros argumentos em seu script, a menos que seja executado em um escopo auxiliar. Também será expandido para *se não houver arquivos no diretório.
Chris Baixo
shopt -s nullglobresolveria isso
glenn jackman
3

Verifique uma das seguintes alternativas:

$ FILE=($(echo *))
$ FILE=$(echo * | grep -o "^\S*")
$ FILE=$(echo * | grep -o "[^ ]*")
$ FILE=$(find . -type f -print -quit)

Então você pode imprimi-lo via echo $FILE.

Veja também: grepa única primeira palavra da saída?

kenorb
fonte
1

Obtendo o primeiro nome de arquivo inteiro:

shopt -s nullglob
printf '%s\000' * | grep -z -m 1 '^..*$'
printf '%s\000' * | ( IFS="" read -r -d "" var; printf '%s\n' "$var" )
Markle
fonte