Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

# trims trailing spaces and tabs from file, using awk utility
function remove_trail() {

[ ! $# -lt 2 ] || { echo "Usage: $FUNCNAME file-to-trim out-file"; return 1; }

    # args

    # this check works fine...

    [ -f "$in" ] && return 0 || { echo "File \""$in"\" does not exist."; return 1; }

    # substitute tabs and spaces for nothing on $in arg, then output result to $out
    awk '{ sub(/[ \t]+$/, ""); print }' "$in" >tmp && mv tmp "$out"
    #however, after previous line I don't get my tmp file nor my $out file created.. WHY :O???
    # give user a friendly message
    echo 'Processing done.. Check your '"$out"' file.'

this function is defined in .bashrc, so I could use it daily as a kind of builtin.. so when I open shell I type remove_trail file1 file2 to get file2 written from file1+removed_trailing_spaces.
My question is: Why I am not getting tmp and $out files created in my dir?

share|improve this question
up vote 2 down vote accepted

The error is in the following line:

[ -f "$in" ] && return 0 || { echo "File \""$in"\" does not exist."; return 1; }

You return from the function if the in parameter to the function is a file. This would explain the absence of the output file.

Perhaps you wanted to say:

[ -f "$in" ] || { echo "File \""$in"\" does not exist."; return 1; }


[ ! -f "$in" ] && { echo "File \""$in"\" does not exist."; return 1; }

Moreover, you wouldn't see the temp file as you move it to the output:

mv tmp "$out"
share|improve this answer
maaan.. i was starting to pull my hair off, that return 0 was overseen totally. thanks ;) – branquito Mar 19 '14 at 14:04
yes of course for the tmp file, I know that, just thought that something with mv went wrong so I said, tmp or $out. :) – branquito Mar 19 '14 at 14:07

Just write it as:

trim() { sed 's/[[:blank:]]*$//'; }

And use it as:

trim < file1 > file2

The rest is superfluous.

To prevent the output file being overwritten, you'd do:

trim() (
  set -C
  sed 's/[[:blank:]]*$//' > "$1"

and use it as:

trim < file1 file2

(note the absence of >).

You could also let trim open the input file, but you'd lose the ability to do things like:

cmd | trim out-file 
share|improve this answer
I marked @devnull answer as a solution, because it gave solution for my script, I know i could use it shortway, but wanted to paractice my bash script skills ;).. But isn't downside of your approach that file2 would be silently overwritten if existed?? – branquito Mar 19 '14 at 14:18
It would also be overwritten with your approach – Stéphane Chazelas Mar 19 '14 at 14:46
yes you are right, i forgot i removed the line where i check for output file.. anyway thanks for your examples, i learned some things, why are you using braces in first case and parenthesis in another, () fires subshell and {} do not, but i don't see why are you using different ones in this example.. – branquito Mar 19 '14 at 23:06
@branquito, to limit the scope of set -C. – Stéphane Chazelas Mar 19 '14 at 23:12
ah ok, i thought of that but wasn't shure. anyway glad to meet you here, i read a lot of your examples going through bash guides (those where they say courtesy of Stephane Chazelas), lot of nice solutions.. ;) – branquito Mar 19 '14 at 23:15

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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