Jeg prøver at fjerne filtypenavnet fra en liste over filer, jeg har genereret med følgende bash script:
#!/bin/bash file_list=$(find . -type f) #assuming that the files are stored in the same directory trimmed_file_list=$(printf "%s\n" "${file_list[@]%.*}") printf "%s\n" "${trimmed_file_list[@]}"
Denne udvidelse trimmer udvidelsen fra sidste posten på listen, men ikke nogen af de tidligere.
For eksempel vil jeg have følgende liste:
file1.pdf file2.pdf file3.png
Bliver
file1 file2 file3
Men i stedet får jeg:
file1.pdf file2.pdf file3
Jeg foretrækker ikke at gøre dette i en løkke, jeg vil gerne bruge parameterudvidelse. Jeg vil undgå at klippe, fordi jeg kun nogensinde vil fjerne den sidste udvidelse i filen.
Der er en hel del emner om parameterudvidelse, og det ser ud til, at bash måske kvæler ved find
” s brug af nye linjer … Jeg er virkelig ikke sikker. Hvis et andet af de allerede eksisterende emner forklarer dette problem, forstår jeg ikke fuldt ud, hvad der foregår.
Emner, der ser ud relateret men synes ikke at løse mit problem:
- Hvordan kan jeg fjerne udvidelsen af et filnavn i et shell-script?
- Udvidelse af shellparametre på arrays
- Droping filnavn udvidelser med find -exec
Kommentarer
- Din titel nævner arrays, men der er ingen matrix i din kode.
- @Kusalananda Tak! Jeg ' er klar over det, siden jeg spurgte. Lærer stadig 🙂
- @Kusalananda Jeg ' er gået videre og ændret spørgsmålet for bedre at matche problemet. Det skulle forhindre fejlagtige google-søgninger i at ramme siden. Tak for oplysningerne!
Svar
Du kan gøre alt i en kommando.
find /path/to -type f -execdir bash -c "printf "%s\n" "${@%.*}"" bash {} +
Kommentarer
- Tak! Jeg har faktisk brug for at oprette et par kopier af arrayet, en til en menu, der har filnavnet ændret, og en, der bevarer den oprindelige indeksværdi, så jeg kan ringe til filen fra menuen. Det er virkelig forbløffende, hvor meget bash dog kan! Evnen til at integrere alt i en kommando sprænger mig stadig væk! : D
Svar
Jeg tror, du vil lave en matrix i stedet for en streng:
IFS=$"\n" # split on newline only set -o noglob # disable the glob part file_list=($(find . -name "*.*" -type f))
Eller med bash 4.4+, ikke bryde på filstier med nye linjetegn:
readarray -td "" file_list < <(find . -name "*.*" -type f -print0)
Derefter skulle din parameterudvidelse fungere, selv om det her ville være mere fornuftigt at bruge en arrayvariabel igen:
trimmed_file_list=("${file_list[@]%.*}")
I din kodeeksempel laver du en streng derefter bede parameterudvidelse om at fjerne alt efter det sidste priktegn i den fulde streng.
Kommentarer
- Tak! Jeg vil teste det, så snart jeg rammer mit skrivebord om morgenen.
- Dette forudsætter, at ingen filnavne i det bibliotek indeholder noget mellemrum eller klodrende tegn.
- @Wildcard skal være adresseret af den seneste redigering.
- @ Wildcard Tak for markøren! Jeg ' m genererer de filer, der er faldet i denne mappe programmatisk, så det burde ikke være ' t et problem.
Svar
Din kode inkluderer ikke arrays. Det sætter også en liste med filnavne i en streng, $file_list
. Indholdet af strengen slutter med file3.png
, og din parameterudskiftning fjerner .png
fra strengen og efterlader dig med en enkelt streng med filnavne, hvor det sidste filnavn har ikke et filnavnesuffiks.
At sætte flere separate objekter (stienavne) i en enkelt streng diskvalificerer automatisk scriptet fra at fungere korrekt for filer, hvis navne indeholder mellemrum (eller den afgrænsning, som strengen bruger). Brug af en matrix hjælper ikke, da du stadig vil opdele output fra find
på mellemrum.
At trimme udvidelsen ud af alle filnavne på almindelige filer i eller under det aktuelle bibliotek:
find . -type f -name "*.*" -exec sh -c " for pathname do printf "Would move %s to %s...\n" "$pathname" "${pathname%.*}" # mv -i "$pathname" "${pathname%.*}" done" sh {} +
Dette søger efter almindelige filer, hvis navne indeholder mindst en prik. Stienavne på disse filer fodres i batches i et lille shell-script, der løber over dem. Shell-scriptet omdøber filerne ved at fjerne den sidste prik i filnavnet og alt, hvad der følger efter. Den aktuelle mv
kommando kommenteres af sikkerhedshensyn.
Kommandoen find
fungerer som en generator af stienavne til internt shell-script, og vi garanteres at behandle stienavne korrekt, der indeholder mellemrum, nye linjer og faner. Der er ikke behov for at gemme output af kommandoer i variabler.
Hvis du har en række stienavne, muligvis oprettet ved hjælp af
shopt -s globstar nullglob file_list=( **/*.* ) # get pathnames of files with dots in their names
Så vil du være i stand til at udstede stienavne uden suffikser med
printf "%s\n" "${file_list[@]%.*}"
Om dette vil hjælpe dig, ved jeg ikke. Hvis du vil bruge stienavnene uden suffikser til noget , så brug af output fra ovenstående printf
kommando ville være forkert ting at gøre (du ville være tilbage ved ikke at håndtere mærkeligt stienavn igen). Så når og hvordan du sletter filnavnesuffikserne afhænger af, hvad du gerne vil gøre med resultatet.
Relateret:
Kommentarer
- Tak! Din mestring af bash er meget tydelig! Jeg ' skraber stadig på overfladen … Tak fordi du tog dig tid til at hjælpe 🙂