Can xargs evaluate $HOME?

Posted on

Problem :

When I type in

echo $HOME/Downloads | xargs cd

It correctly changes directory to $HOME/Downloads. Maybe that is because echo evaluates $HOME before piping to xargs.

However if I type

echo '$HOME/Downloads' | xargs cd

$HOME/Downloads is passed as it is to xargs and it fails to change directory. It gives an error:

/usr/bin/cd: line 4: cd: $HOME/Downloads: No such file or directory

So my question is can xargs evaluate $HOME, if it can how.

Solution :

Bash variables can only be evaluated by the bash shell.

When you echo '$HOME/dir' and pipe the results to another command, you are telling bash to not evaluate the variable and treat the parameter as a string.

xargs (and most other commands) don’t have a concept of bash variables – they would need to invoke a bash shell to evaluate them. For example:

echo '$HOME/dir' | xargs bash -c cd 

This would invoke a bash shell which would evaluate the variable and cd into the correct director. However upon completion, the shell would terminate and return control to the original shell (which would still be in the starting directory.

So it works, but probably not how you want it too.

Paul’s explanation is correct. My reply in the following was written before Anurag Peshne kindly re-explained to me what he meant, see comments below. I am leaving my reply as it stands even though it is not relevant because it seems to me cowardly to hide my errors.

The expression which does not work as the original OP would like contains:

    echo '$HOME/Downloads'

that is, a shell variable inside single quotes, ''. This is standard bash shell lingo for do not evaluate the expression inside the single quotes. In fact,

    $ echo '$HOME/Downloads'
    $ echo "$HOME/Downloads"

Notice the difference between using single quotes, '', and double quotes, " ", which instead mean: do substitute variables.

In fact, the Bash manual has this to say about this difference: Single Quotes

Enclosing characters in single quotes (‘’’) preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash. Double Quotes

Enclosing characters in double quotes (‘”’) preserves the literal value of all characters within the quotes, with the exception of ‘$’, ‘`’, ‘’, and, when history expansion is enabled, ‘!’. The characters ‘$’ and ‘`’ retain their special meaning within double quotes (see Shell Expansions). The backslash retains its special meaning only when followed by one of the following characters: ‘$’, ‘`’, ‘”’, ‘’, or newline. Within double quotes, backslashes that are followed by one of these characters are removed. Backslashes preceding characters without a special meaning are left unmodified. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ‘!’ appearing in double quotes is escaped using a backslash. The backslash preceding the ‘!’ is not removed.

The special parameters ‘*’ and ‘@’ have special meaning when in double quotes (see Shell Parameter Expansion).

In short, the commands displayed by the OP work exactly as the Bash manual states, and this whole business is totally urelated to the behavior of xargs.

Leave a Reply

Your email address will not be published. Required fields are marked *