1

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

#!/bin/bash ## shell type
dir_in=('/Users/dossa013/data/inland-data/input/')
dir_out=('/Volumes/Macintosh HD 2/data/cmip5/cru/')

files=('/Users/dossa013/data/inland-data/input/*ts*')

where the variable "files" contains the following:

cld.cru_ts3.22.1901.2013.nc
prec.cru_ts3.22.1901.2013.nc
rh.cru_ts3.22.1901.2013.nc
temp.cru_ts3.22.1901.2013.nc
trange.cru_ts3.22.1901.2013.nc
wetd.cru_ts3.22.1901.2013.nc

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")

done

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?

2 Answers2

1

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

originalfilename=rh.cru_ts3.22.1901.2013.nc

tmpfn=${originalfilename%.*}
extfn=${originalfilename##*.}
newfilename=${tmpfn}_cropped.${extfn}

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

Output:

rh.cru_ts3.22.1901.2013.nc
rh.cru_ts3.22.1901.2013_cropped.nc
Janis
  • 14,222
  • You should really make a habit to use more quotes just in case files contain spaces or new lines. – Valentin Bajrami May 06 '15 at 09: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 06 '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 06 '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 06 '15 at 10:31
  • @Janis, your answer did the trick. Thank you. – thiagoveloso May 06 '15 at 17:44
0

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 06 '15 at 09:18
  • @thiagoveloso Using basename is discouraged. You are doing just fine using parameter expansion so keep using that. – Valentin Bajrami May 06 '15 at 09:31
  • @val0x00ff Please could you explain why basename is discouraged? – Carl H May 06 '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: http://mywiki.wooledge.org/BashFAQ/100?highlight=%28basename%29 – Valentin Bajrami May 06 '15 at 11:11