Suppose I have a subdirectory called sub
. Then I want to operate on all files in that directory with the extension "txt". I want something like
for f in sub/*.txt
do
enscript -b "" -o {$f basename excluding .txt}.ps sub/{$f basename excluding .txt}.txt
ps2pdf {$f basename excluding .txt}.ps {$f basename excluding .txt}.pdf
done
So if there was just one file in the sub
directory of the form *.txt
, say sub/foo.txt
, the script should expand to
enscript -b "" -o foo.ps sub/foo.txt
ps2pdf foo.ps foo.pdf
I generally prefer portable solutions, but it is always interesting to learn about different ways of doing things. So non-portable is Ok, please just mention whether your solution is portable or non-portable. Also, the title is probably not the best possible, so feel free to modify.
EDIT: I realized the example as written did not quite make sense, since foo.txt
was in the sub
directory, and therefore sub/foo.txt
would need to be passed to enscript
. I also changed the -p enscript
option to the more standard -o
option.
Best Answer
POSIX shells (e.g., bash, dash, ksh, …) accept a
${var%suffix}
construct that can be used to remove the trailing portion from the value of a variable. For instance, ifpath="sub/file.txt"
, then${path%.txt}
expands tosub/file
.There's a symmetric construct to remove a prefix:
${var#prefix}
. The prefix can be a pattern. Doubling the#
strips the longest matching prefix. For example, ifpath=sub/dir/file.txt
, then${path##*/}
expands tofile.txt
(and${path#*/}
expands todir/file.txt
). The same goes for suffixes and%
.So, in your case you could write this (note that you can't combine the prefix stripping and the suffix stripping into a single expansion, at least not with only POSIX constructs):
Alternatively, the GNU basename command accepts an optional second argument which is the file extension to remove. For instance, if
$f
isfile.txt
, then$(basename $f .txt)
expands tofile
.Note, however, that
basename
removes all path information except for the last component, so if you want to remove just the extension you have to put that back (see the dirname command).