shell alias executes in home directory

223 views Asked by At

I have following line in my .zshrc file:

alias clean="sed -i 's/\r//g; s/    /\t/g' $(find . -maxdepth 1 -type f)"

but when I try to execute it in /path/to/some/directory the output is:

sed ./.Xauthority
./.lesshst: No such file or directory

.Xauthority and .lesshst are both in my home directory.

Substitutiong . with $(pwd) dos not help.

1

There are 1 answers

0
markp-fuso On BEST ANSWER

When defining the alias you've used double quotes to encompass the entire (alias) definition. This has the effect of actually running the find command at the time the alias is defined.

So when the alias is created it will pick up a list of files from the directory in which the alias is being defined (eg, in your home directory when sourcing .zshrc).

You can see this happening in the following example:

$ cd /tmp

$ pwd
/tmp

$ ls -l
total 36036
drwxrwxrwt+ 1 myid None                  0 Oct 10 11:31 ./
drwxr-xr-x+ 1 myid None                  0 Jul 12 17:28 ../
-rw-r--r--  1 myid Administrators        0 Oct 10 11:31 a
-rw-r--r--  1 myid Administrators        0 Oct 10 11:31 b
-rw-r--r--  1 myid Administrators        0 Oct 10 11:31 c
-rw-r--r--  1 myid Administrators        0 Oct 10 11:31 d
-rw-r--r--  1 myid Administrators 36864002 Jun  6 17:29 giga.txt
drwx------+ 1 myid Administrators        0 Mar  8  2020 runtime-xward/

$ alias clean="sed -i 's/\r//g; s/    /\t/g' $(find . -maxdepth 1 -type f)"
$ alias clean
alias clean='sed -i '\''s/\r//g; s/    /\t/g'\'' ./a
./b
./c
./d
./giga.txt'

Notice how the find was evaluated at alias definition time and pulled in all of the files in my /tmp directory.

To address this issue you want to make sure the find is not evaluated at the time the alias is created.

There are a few ways to do this, one idea being to wrap the find portion of the definition in single quotes, another idea would be keep the current double quotes and just escape the $, eg:

$ alias clean="sed -i 's/\r//g; s/    /\t/g' "'$(find . -maxdepth 1 -type f)'
$ alias clean
alias clean='sed -i '\''s/\r//g; s/    /\t/g'\'' $(find . -maxdepth 1 -type f)'

$ alias alias clean="sed -i 's/\r//g; s/    /\t/g' \$(find . -maxdepth 1 -type f)"
$ alias clean
alias clean='sed -i '\''s/\r//g; s/    /\t/g'\'' $(find . -maxdepth 1 -type f)'

Notice in both cases the alias contains the actual find command instead of the results of evaluating it in the current directory.