I have a set of files with a given suffix. For instance, I have a set of pdf files with suffix .pdf
. I would like to obtain the names of the files without the suffix using substring expansion.
For a single file I can use:
file="test.pdf"
echo ${file:0 -4}
To do this operation for all files, I now tried:
files=( $(ls *.pdf) )
ff=( "${files[@]:0: -4}" )
echo ${ff[@]}
I now get an error saying that substring expression < 0
..
( I would like to avoid using a for
loop )
Use parameter expansions to remove the .pdf
part like so:
shopt -s nullglob
files=( *.pdf )
echo "${files[@]%.pdf}"
The shopt -s nullglob
is always a good idea when using globs: it will make the glob expand to nothing if there are no matches.
"${files[@]%.pdf}"
will expand to an array with all the trailing .pdf
removed. You can, if you wish put this in another array as so:
files_noext=( "${files[@]%.pdf}" )
All this is 100% safe regarding funny symbols in filenames (spaces, newlines, etc.), except for the echo
part for files named -n.pdf
, -e.pdf
and -E.pdf
... but the echo
was just here for demonstration purposes. Your files=( $(ls *.pdf) )
is really really bad! Do never parse the output of ls
.
To answer your comment: substring expansions don't work on each field of the array. Taken from the reference manual linked above:
${parameter:offset}
${parameter:offset:length}
If
offset
evaluates to a number less than zero, the value is used as an offset from the end of the value ofparameter
. Iflength
evaluates to a number less than zero, andparameter
is not@
and not an indexed or associative array, it is interpreted as an offset from the end of the value ofparameter
rather than a number of characters, and the expansion is the characters between the two offsets. Ifparameter
is@
, the result islength
positional parameters beginning at offset. Ifparameter
is an indexed array name subscripted by@
or*
, the result is thelength
members of the array beginning with${parameter[offset]}
. A negative offset is taken relative to one greater than the maximum index of the specified array. Substring expansion applied to an associative array produces undefined results.
So, e.g.,
$ array=( zero one two three four five six seven eight )
$ echo "${array[@]:3:2}"
three four
$
来源:https://stackoverflow.com/questions/20160838/bash-substring-expansion-on-array