0

I would like to do following:

  1. get all dependencies (dir names)
  2. get basename of current directory
  3. since current directory is not a dependency, get rid of it
  4. print them

what I have so far (from bashrc):

export dep=$({ tmp=$(ls /usr/local/lib/node_modules/); echo ${tmp//$(basename $(pwd))/}; })

The goal is it to have it in variable, not a function or alias becuase I want to use it later (such as for npm link $dep), which I would not be able if it was function.

But the current output DOES include the current directory. Was it invoked from the current dir, the current dir would not be included. So I guess the variable is not reexecuted to take into account it changed its dir (from where bashrc is, to where I am now).

So how to make it to NOT include the current dir?

milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • `which I would not be able if it was function` : You can do: `npm link $(fndep)` with a function – anubhava Jun 05 '22 at 09:41
  • Tangentially, unless you have a tool which requires `dep` to be visible in its environment when it runs, the `export` is unnecessary here. – tripleee Jun 05 '22 at 09:42
  • @anubhava well yes, but still be better as variable as variable is more versatile – milanHrabos Jun 05 '22 at 09:44
  • Also tangentially, [don't parse the output of `ls`](http://mywiki.wooledge.org/ParsingLs). Your code could be refactored to `( cd /usr/local/lib/node_modules; printf '%s\n' * )` – tripleee Jun 05 '22 at 09:45
  • Huh? A static variable is _less_ versatile than a function you call dynamically when you need to. – tripleee Jun 05 '22 at 09:46
  • @milanHrabos: You have to make a decision based on your requirement of static or dynamic? Moment you think of a dynamic value you have to use function – anubhava Jun 05 '22 at 09:48
  • But in this case, the variable is made from dynamic calls `$(...)`, so I would expect that it would consequently have dynamic behaviour. I don't know, if that is the reason why it does not work. – milanHrabos Jun 05 '22 at 09:50
  • The variable simply contains static text which gets evaluated at the time you assign it. – tripleee Jun 05 '22 at 09:52

1 Answers1

0

A variable is simply static text, the shell (or, let alone, the string itself) in no way keeps track of how its value was calculated; it's just a sequence of characters. If you need the value to change depending on external circumstances, you need to assign it again in those circumstances, or simply use a script or a function instead of a variable.

Here is a simple function which avoids trying to parse the output from ls:

getdep () {
    ( cd /usr/local/lib/node_modules
      printf '%s\n' * ) |
    grep -vFx "$(basename "$(pwd)")"
}

You would call it like

dep=$(getdep)

when you need to update dep, or simply use $(getdep) instead of $dep.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Well I used `dep(){ find $node_modules -mindepth 1 -maxdepth 1 -printf "%f " | sed "s/$(basename $(pwd))//"; }`, but got the same result – milanHrabos Jun 05 '22 at 10:07
  • 1
    The difference is mainly that you will get mangled entries for any module whose name contains the current directory. If your current directory is `foo` and you have a dependency `foobar`, it will be printed as `bar`, which is obviously a bug. `find` is much heavier than `printf` but functionally the two are equivalent, and `find` offers many options if you need something more complicated than just a simple list. (So, for example, `find ... -not -name "$(basename $(pwd))" -printf ...` would avoid the (buggy) `sed`. – tripleee Jun 05 '22 at 10:10
  • The lack of quoting is also a bug; see [When to wrap quotes around a shell variable?](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable) – tripleee Jun 05 '22 at 10:12
  • I decided to use the version of `find` where negating the basename. Find seems to me more elegant then changing directories. – milanHrabos Jun 05 '22 at 10:17