Search code examples
bashargumentsfoldcommand-substitution

fold: invalid number of columns when running script with arguments


I got a strange behavior when running a script with arguments that contains a command substitution. I would like to understand why is this behavior happening. The script is:

#!/bin/bash

# MAIL=$1
# USER=$2
PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-20} | head -n 1);
echo "$PASSWORD"

Then I run: ./test.sh mail user, I get the error: fold: invalid number of columns: ‘mail’ and the Password is not generated.

If I don't pass an argument or I don't generate the password, it works fine.

Update (for understanding the behavior)

I think I've found out what is happening: When running a script with two arguments the $1 and $2 have the passed values. Example: ./test.sh arg1 arg2 have $1 -> arg1 and $2 -> arg2

When using a pipe inside a script, the original arguments are still passed and thus if you have two arguments as input you will have the piped output inserted into the third place $3.

  • $1 -> arg1
  • $2 -> arg2
  • $3 -> piped output So a working solution would be:
PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${3:-20} | head -n 1);

but if you vary the input arguments, it will not work. Therefore the best solution is what @KamilCuk suggested:

PASSWORD=$(< /dev/urandom tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1);

Solution

  • If you do not wish to pass the first script argument to fold, then do not use $1 in it.

    PASSWORD=$(< /dev/urandom tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1);
    #                                                      ^^ - pass the number, not $1
    echo "$PASSWORD"