So I have my input directory, output directory and list of files:

#!/bin/bash ## shell type
dir_out=('/Volumes/Macintosh HD 2/data/cmip5/cru/')


where the variable "files" contains the following:


What I need to do is run a command that requires as arguments an input file and an output file. In my case, the directory where the input files are located is different from the output files directory.

The caveat is: when specifying the output file, I would like to append the word "croppped" between the end of the original filename and the extension.

This loop doesn't work:

for f in ${files[@]}; do ## loop over files

echo cdo sellonlatbox "${dir_in}"${f##*/} "${dir_out}"$(printf '%s\n' "${f##*/.nc}_cropped.nc")


Ideally, the result would be:

cdo sellonlatbox /Users/dossa013/data/inland-data/input/prec.cru_ts3.22.1901.2013.nc /Volumes/Macintosh HD 2/data/cmip5/cru/prec.cru_ts3.22.1901.2013_cropped.nc

Where is my mistake here?


Here is an example using one of your sample file names (but working on arbitrary file extensions):



printf "%s\n" "${originalfilename}" "${newfilename}"


  • You should really make a habit to use more quotes just in case files contain spaces or new lines. – Valentin Bajrami May 6 '15 at 9:55
  • oh really, I hope you are not serious. Quotes are crusial in bash for the above mentioned reasons. touch "file with spaces"; var="file with spaces"; cat $var && cat "$var" Notice the difference. In this case I'm using cat but imagine if one used rm. This will have very bad side effects. Avoid it if unnecessary! is just a bad advice. – Valentin Bajrami May 6 '15 at 10:28
  • @val0x00ff; You should be aware that there are no quotes necessary in those shell assignments. Adding superflouous quotes makes the shell code even less legible than it typically already is, so better avoid it in unnecessary places! – Janis May 6 '15 at 10:28
  • @val0x00ff; cat is a command; its arguments (similar to using other [external] commands) need quoting to prevent the well known problems. But this is different from pure shell assignments! - Please read the shell docs to understand that difference. - (And how can avoidance of something unnecessary be bad advice? - The opposite is true!) – Janis May 6 '15 at 10:31
  • @Janis, your answer did the trick. Thank you. – thiagoveloso May 6 '15 at 17:44

You can use basename to remove the extension and then add the new extension:

 croppedname=$(basename $originalname .nc)_cropped.nc

basename also removes the directory, so you can prepend your destination directory.

  • It worked, thanks, but I would prefer using only bash commands because my real data contains thousands of files and basename can be really slow in this case. – thiagoveloso May 6 '15 at 9:18
  • @thiagoveloso Using basename is discouraged. You are doing just fine using parameter expansion so keep using that. – Valentin Bajrami May 6 '15 at 9:31
  • @val0x00ff Please could you explain why basename is discouraged? – Carl H May 6 '15 at 10:59
  • 1
    @CarlH basename(1) can strip the directory and extension from a path (directory/subdirectory/filename.extension -> filename.extension or filename). A parameter expansion can do it cleaner and much faster: "${path##*/}", "${path%.*}", at the cost of missing corner cases like path=/ For more see: mywiki.wooledge.org/BashFAQ/100?highlight=%28basename%29 – Valentin Bajrami May 6 '15 at 11:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.