Hoe verwijder ik het bestandstift en het padgedeelte van een padstring in bash?

Gegeven een string-bestandspad zoals /foo/fizzbuzz.bar, hoe zou ik bash gebruiken om alleen de fizzbuzzgedeelte van genoemde tekenreeks te extraheren?


Antwoord 1, Autoriteit 100%

Hier is hoe het te doen met de # en% operators in bash.

$ x="/foo/fizzbuzz.bar"
$ y=${x%.bar}
$ echo ${y##*/}
fizzbuzz

${x%.bar}kan ook ${x%.*}om alles te verwijderen na een punt of ${x%%.*}om alles na de eerste punt te verwijderen.

Voorbeeld:

$ x="/foo/fizzbuzz.bar.quux"
$ y=${x%.*}
$ echo $y
/foo/fizzbuzz.bar
$ y=${x%%.*}
$ echo $y
/foo/fizzbuzz

Documentatie is te vinden in de BASH-handleiding . Zoek naar ${parameter%word}en ${parameter%%word}trailing portie matching sectie.


Antwoord 2, Autoriteit 40%

Kijk naar het Basename-opdracht:

NAME="$(basename /foo/fizzbuzz.bar .bar)"

instrueert het om het achtervoegsel te verwijderen .bar, resulteert in NAME=fizzbuzz


Antwoord 3, Autoriteit 8%

Pure bash, gedaan in twee afzonderlijke operaties:

  1. Verwijder het pad van een pad-string:

    path=/foo/bar/bim/baz/file.gif
    file=${path##*/}  
    #$file is now 'file.gif'
    
  2. Verwijder de extensie van een pad-string:

    base=${file%.*}
    #${base} is now 'file'.
    

Antwoord 4, Autoriteit 3%

Basename gebruiken Ik heb het volgende gebruikt om dit te bereiken:

for file in *; do
    ext=${file##*.}
    fname=`basename $file $ext`
    # Do things with $fname
done;

Dit vereist geen priori-kennis van de bestandsextensie en werkt, zelfs als u een bestandsnaam hebt die stippen in zijn bestandsnaam (voor zijn extensie) heeft; Het vereist het programma basenameHoewel, maar dit maakt deel uit van de GNU COREUTILS, zodat het met elke distro moet worden verzonden.


Antwoord 5, Autoriteit 2%

De Basename en Dirname-functies zijn wat u zoekt:

mystring=/foo/fizzbuzz.bar
echo basename: $(basename "${mystring}")
echo basename + remove .bar: $(basename "${mystring}" .bar)
echo dirname: $(dirname "${mystring}")

heeft de uitvoer:

basename: fizzbuzz.bar
basename + remove .bar: fizzbuzz
dirname: /foo

Antwoord 6, Autoriteit 2%

Pure bash-manier:

~$ x="/foo/bar/fizzbuzz.bar.quux.zoom"; 
~$ y=${x/\/*\//}; 
~$ echo ${y/.*/}; 
fizzbuzz

Deze functionaliteit wordt uitgelegd op man bash onder “parameter expansion”. Non Bash-manieren in overvloed: Awk, Perl, SED enzovoort.

EDIT: werkt met stippen in bestand achtervoegsels en hoeft het achtervoegsel (extensie) niet te kennen, maar werkt niet werk met stippen in de naam zelf.


Antwoord 7

Gebruik basenameAangenomen dat u weet wat de bestandsextensie is, nietwaar?

En ik geloof dat de verschillende suggesties voor reguliere expressies niet opgewassen zijn tegen een bestandsnaam met meer dan één “.”

Het volgende lijkt te gaan met dubbele punten. Oh, en bestandsnamen die zelf een “/” bevatten (alleen voor de kick)

Om Pascal te parafraseren: “Sorry, dit script is zo lang. Ik had geen tijd om het korter te maken”


  #!/usr/bin/perl
  $fullname = $ARGV[0];
  ($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/;
  ($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/;
  print $basename . "\n";

Antwoord 8

In aanvulling op de POSIX-conforme syntaxisgebruikt in dit antwoord,

basename string [suffix]

zoals in

basename /foo/fizzbuzz.bar .bar

GNU basenameondersteunt een andere syntaxis:

basename -s .bar /foo/fizzbuzz.bar

met hetzelfde resultaat. Het verschil en voordeel is dat -s-aimpliceert, wat meerdere argumenten ondersteunt:

$ basename -s .bar /foo/fizzbuzz.bar /baz/foobar.bar
fizzbuzz
foobar

Dit kan zelfs bestandsnaam veilig worden gemaakt door de uitvoer te scheiden met NUL BYTES met behulp van de optie -z, bijvoorbeeld voor deze bestanden met blanco, newlines en globetekens (geciteerd door ls):

$ ls has*
'has'$'\n''newline.bar'  'has space.bar'  'has*.bar'

lezen in een array:

$ readarray -d $'\0' arr < <(basename -zs .bar has*)
$ declare -p arr
declare -a arr=([0]=$'has\nnewline' [1]="has space" [2]="has*")

readarray -dvereist bash 4.4 of nieuwer. Voor oudere versies moeten we lus:

while IFS= read -r -d '' fname; do arr+=("$fname"); done < <(basename -zs .bar has*)

Antwoord 9

perl -pe 's/\..*$//;s{^.*/}{}'

Antwoord 10

Als u basenaam niet kunt gebruiken zoals gesuggereerd in andere berichten, kunt u altijd SED gebruiken. Hier is een (lelijk) voorbeeld. Het is niet de beste, maar het werkt door de gewenste string te extraheren en de invoer te vervangen door de gewenste string.

echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g'

Hiermee krijgt u de uitvoer

Fizzbuzz


Antwoord 11

Pas op voor de voorgestelde PERL-oplossing: het verwijdert alles na de eerste punt.

$ echo some.file.with.dots | perl -pe 's/\..*$//;s{^.*/}{}'
some

Als u het met PERL wilt doen, werkt dit:

$ echo some.file.with.dots | perl -pe 's/(.*)\..*$/$1/;s{^.*/}{}'
some.file.with

Maar als je Bash gebruikt, de oplossingen met y=${x%.*}(of basename "$x" .extals je de extensie kent ) zijn veel eenvoudiger.


Antwoord 12

Het best beoordeelde antwoord combineren met het op één na best beoordeelde antwoord om de bestandsnaam te krijgen zonder het volledige pad:

$ x="/foo/fizzbuzz.bar.quux"
$ y=(`basename ${x%%.*}`)
$ echo $y
fizzbuzz

Antwoord 13

De basisnaam doet dat, verwijdert het pad. Het zal ook het achtervoegsel verwijderen als het wordt gegeven en als het overeenkomt met het achtervoegsel van het bestand, maar u moet het achtervoegsel weten om aan de opdracht te geven. Anders kun je mv gebruiken en op een andere manier uitzoeken wat de nieuwe naam zou moeten zijn.


Antwoord 14

U kunt gebruiken

mv *<PATTERN>.jar "$(basename *<PATTERN>.jar <PATTERN>.jar).jar"

Bijvoorbeeld: – Ik wilde -SNAPSHOTuit mijn bestandsnaam verwijderen. Voor dat gebruikte onderstaande commando

mv *-SNAPSHOT.jar "$(basename *-SNAPSHOT.jar -SNAPSHOT.jar).jar"

Other episodes