Obtenha a parte de uma linha antes da última barra

5

Estou tentando escrever um script conky que mostre a arte do meu álbum MPD, um 'folder.jpg' na pasta do álbum. Meu plano atual é usar mpc -f %file% , que imprime o nome do arquivo e o caminho e, em seguida, recorta o nome real do arquivo (ou seja, após o último /) e usa esse caminho como o objeto de imagem do conky. p>

Estou tendo problemas com o grep / cut, principalmente porque algumas músicas estão aninhadas em duas pastas, enquanto outras estão em uma. ( grep -m 1 . |cut -f1 -d / funciona para os álbuns de pasta única)

Como eu faria isso? Existe uma maneira mais simples que eu sinto falta?

    
por rargh 03.09.2014 / 00:42

3 respostas

8

Você pode usar sed para remover o restante - tudo começando com a última barra :

mpc -f %file% | head -1 | sed 's:/[^/]*$::'

O padrão /[^/]*$ corresponde a uma barra, seguida por qualquer caractere, exceto barra, até o final da linha. É substituído pela string vazia.
O head -1 ignora alguma saída de status seguindo a linha que queremos - mas veja abaixo como não prendê-los em primeiro lugar.

Caso você não esteja acostumado a sed, o comando pode parecer incomum por causa do : usado. Você pode ter visto os comandos sed com / como separador antes, como 's/foo/bar/' - prefiro usar o separador : para legibilidade, pois a expressão contém / em si. Alternativamente, poderíamos escapar do / na expressão: 's/\/[^\/]*$//' - que não o torna mais legível.

A maneira como você o usa com mpc fornece duas linhas de status adicionais. A opção -q para quiet desliga toda a saída. Você precisa combinar -q com a impressão explícita do arquivo atual para obter a linha que você precisa, e nada mais:

mpc -q -f %file% current | sed 's:/[^/]*$::'

Em vez de remover tudo a partir da última barra , pode-se imprimir explicitamente tudo antes da última barra :

mpc -q -f %file% current | sed 's:^\(.*\)/.*$::'

Corresponde a quaisquer caracteres que sejam seguidos por / e quaisquer outros caracteres; Ele corresponde o máximo possível, para que o / correspondido seja o último.

    
por 03.09.2014 / 00:54
3

Se você quiser aplicar essa regra em uma única string, em vez de sed (veja a outra resposta), use o comando dirname :

$ dirname "1 2/3 4/5 6/file"
1 2/3 4/5 6
    
por 03.09.2014 / 00:56
2

O Grep não é a última ferramenta para o trabalho. grep -m 1 . imprime a primeira linha não vazia, o que não é útil. Você pode construir soluções complexas que envolvem o grep e outras ferramentas, mas a maneira direta é com sed . Uma maneira é substituir uma sequência final de caracteres não slash, mais a barra anterior, pela string vazia:

mpc -f %file% | sed 's:/[^/]*$::'

Como alternativa, mantenha tudo na última barra e descarte o que segue:

mpc -f %file% | sed 's:^\(.*\)\(/.*\)$::'

Tenha em atenção que ambos os métodos deixam a entrada inalterada se não contiverem / , ou seja, se passar um nome de ficheiro sem indicação de diretório. Embora você possa resolver isso em sed se for um problema, é mais fácil invocar o dirname command :

dirname -- "$(mpc -f %file%)"

Em um script de shell, você também pode usar a expansão de parâmetro constrói, mas isso é mais complexo se você quiser apenas imprimir o resultado:

full_path="$(mpc -f %file%)"
case "$full_path" in
  */*) directory_part="${full_path%/*}"
  *) directory_part="."
printf '%s\n' "$directory_part"
    
por 03.09.2014 / 01:00