Obtenir la partie d'une ligne avant la dernière barre oblique

J'essaye d'écrire un script conky qui montre mon art d'album MPD, un 'folder.jpg' dans le dossier de l'album. Mon plan actuel est d'utiliser mpc -f %file% , qui mpc -f %file% le nom et le path du file, puis découpe le nom du file (c'est-à-dire tout après le dernier /) et l'utilise comme path d'access à l'object image de conky .

J'ai des problèmes avec grep / cut, d'autant plus que certaines chansons sont nestedes dans deux dossiers, alors que d'autres en sont une. ( grep -m 1 . |cut -f1 -d / fonctionne pour les albums à dossier unique)

Comment pourrais-je y aller? Y a-t-il un moyen plus simple qui me manque?

Vous pouvez utiliser sed pour supprimer le rest – tout commençant par la dernière barre oblique :

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

Le motif /[^/]*$ correspond à une barre oblique, suivi de tous les caractères sauf barre oblique, jusqu'à la fin de la ligne. Il est remplacé par la string vide.
La head -1 ignore une sortie d'état suivant la ligne que nous voulons – mais voir ci-dessous pour savoir comment ne pas les pring en premier lieu.

Dans le cas où vous n'êtes pas habitué à sed, la command peut sembler inhabituelle à cause de : used. Vous avez peut-être vu des commands sed avec / comme séparateur avant, comme 's/foo/bar/' – Je préfère utiliser le séparateur : pour la lisibilité, car l'expression contient / elle / même. Sinon, nous pourrions échapper à / dans l'expression: 's/\/[^\/]*$//' – qui ne le rend pas plus lisible.


La façon dont vous l'utilisez avec mpc vous donne deux lignes de statut supplémentaires. L'option -q pour le silence éteint toute la sortie. Vous devez combiner -q avec l'printing explicite du file en cours de lecture pour get la ligne dont vous avez besoin, et rien de plus:

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

Au lieu de tout supprimer à partir de la dernière barre oblique , on pourrait tout imprimer avant la dernière barre oblique :

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

Cela correspond à tous les caractères suivis par un / et tout autre caractère; Il correspond autant que possible, de sorte que le / qui est apparié sera le dernier.

Si vous souhaitez appliquer cette règle à une seule string, vous pouvez utiliser la command dirname au lieu de sed (voir l'autre réponse):

 $ dirname "1 2/3 4/5 6/file" 1 2/3 4/5 6 

Grep n'est pas le dernier outil pour le travail. grep -m 1 . imprime la première ligne non vide, ce qui n'est pas utile. Vous pouvez build des solutions complexes qui impliquent grep et d'autres outils, mais la façon simple est avec sed . Une façon consiste à replace une dernière série de caractères non-slash, plus la barre oblique précédente, par la string vide:

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

Alternativement, gardez tout jusqu'au dernier slash et jetez ce qui suit:

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

Attention, les deux methods laissent l'input inchangée si elle ne contient pas / , c'est-à-dire si vous passez un nom de file sans indication de directory. Bien que vous puissiez résoudre ce problème dans sed si c'est un problème, il est plus facile d'appeler la command dirname :

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

Dans un script shell, vous pouvez également utiliser des constructions de développement de parameters , mais cela est plus complexe si vous voulez simplement imprimer le résultat:

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