Bash expanding substring over array
I have a set of files with a given suffix. For example, I have a set of PDFs with a suffix .pdf
. I would like to get filenames without suffix using substring expansion.
For one file, I can use:
file="test.pdf"
echo ${file:0 -4}
To perform this operation on all files, I have now tried:
files=( $(ls *.pdf) )
ff=( "${files[@]:0: -4}" )
echo ${ff[@]}
Now I am getting an error substring expression < 0
..
(I would like to avoid using a loop for
)
source to share
Use parameter extensions to remove a part .pdf
like this:
shopt -s nullglob
files=( *.pdf )
echo "${files[@]%.pdf}"
shopt -s nullglob
it's always a good idea when using globs: it will cause the glob to not grow to zero if there is no match.
"${files[@]%.pdf}"
will expand to an array with all trailing ones .pdf
removed. You can if you want to put it in another array like this:
files_noext=( "${files[@]%.pdf}" )
All of this is 100% safe with respect to funny characters in filenames (spaces, newlines, etc.), except for the part echo
for files named -n.pdf
, -e.pdf
and -e.pdf
... but echo
was here for demonstration purposes only. Yours is files=( $(ls *.pdf) )
really very bad! Never parse the output ls
.
To answer your comment: substring extensions don't work on every field of an array. Taken from the reference guide above:
${parameter:offset}
${parameter:offset:length}
If
offset
evaluates to a number less than zero, this value is used as the offset from the end of the valueparameter
. Iflength
evaluates to a number less than zero, ratherparameter
than an@
indexed or associative array, it is interpreted as an offset from the end of the valueparameter
, not a number of characters, and the extension is characters between two offsets. Ifparameter
-@
, the result islength
positional parameters starting at offset. Ifparameter
is an indexed array name matched by@
or*
, the result islength
array members starting with${parameter[offset]}
.The 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.
For example,
$ array=( zero one two three four five six seven eight )
$ echo "${array[@]:3:2}"
three four
$
source to share