15

In bash I am trying to glob a list of files from a directory to give as input to a program. However I would also like to give this program the list of filenames

files="/very/long/path/to/various/files/*.file"

So I could use it like that.

prompt> program -files $files -names $namelist

If the glob gives me :

/very/long/path/to/various/files/AA.file /very/long/path/to/various/files/BB.file /very/long/path/to/various/files/CC.file /very/long/path/to/various/files/DD.file /very/long/path/to/various/files/ZZ.file

I'd like to get the list of AA BB CC DD ZZ to feed my program without the long pathname and file extension. However I have no clue on how start there ! Any hint much appreciated !

Benoit B.
  • 11,854
  • 8
  • 26
  • 29

3 Answers3

28

It's better to use an array to hold the filenames. A string variable will not handle filenames which contain spaces.

Also, you don't need to use the basename command. Instead use bash's built-in string manipulation.

Try this:

files=( /very/long/path/to/various/files/*.file )
for file in "${files[@]}"
do
  filename="${file##*/}"
  filenameWithoutExtension="${filename%.*}"
  echo "$filenameWithoutExtension"
done
dogbane
  • 266,786
  • 75
  • 396
  • 414
9

Solution with basename for your question

for file in $files
do
  file_name=$(basename $file)
  file_name_witout_ext=${file_name%.file}
done

edit (generic way to extract filename without (single) extension)

for file in $files
do
  file_name=$(basename $file)
  file_name_witout_ext=${file_name%.*}
done

Another thing that can happen is to have filename like "archive.tar.gz". In this case you will have two (or multiple extension). You can then use a more greddy operator

for file in $files
do
  file_name=$(basename $file)
  file_name_witout_ext=${file_name%%.*}
done
epsilon
  • 2,849
  • 16
  • 23
  • +1 You can be more general using `filename_without_extension="${filename%.*}"`, taken from http://stackoverflow.com/a/965072/1983854 – fedorqui Sep 17 '13 at 09:25
  • excat fedorqui, it may be a good thing. I just stick to the OP parameters. – epsilon Sep 17 '13 at 09:28
3

It's simpler like this:

files=(/very/long/path/to/various/files/*.file)
names=("${files[@]##*/}") names=("${names[@]%.*}")
progname -files "${files[@]}" -names "${names[@]}"

Or if you could only pass them as a single argument:

progname -files "${files[*]}" -names "${names[*]}"
konsolebox
  • 72,135
  • 12
  • 99
  • 105