0

How do I grep this command that includes a wildcard?

How do I grep stderr?

The grep does not seem to do anything:

$ less /Users/raine/.nvm/versions/node/v5.5.0/lib/node_modules/* | grep "Not a file"
/Users/raine/.nvm/versions/node/v5.5.0/lib/node_modules/truffle is a directory
/Users/raine/.nvm/versions/node/v5.5.0/lib/node_modules/wunderline is a directory
/Users/raine/.nvm/versions/node/v5.5.0/lib/node_modules/yo is a directory

This is a very hacky use of less, and probably worthy of another question, but my intention is to find broken symlinks in this directory. It happens to be that less will print is a directory if it is valid and Not a file or directory if it is invalid. I believe it is worth asking anyway as this is indicative of my lack of understanding of wildcard operators stderr.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Raine Revere
  • 190
  • 1
  • 11
  • Clarified intention in OP. – Raine Revere Jun 29 '16 at 16:59
  • You have a valid point! I didn't ask the question directly. I would like to defend myself by saying that many quirky situations offer learning opportunities. In this case, I felt like it was an opportunity to learn more about the interaction between wildcards and grep. – Raine Revere Jun 29 '16 at 17:04
  • 3
    `less ... 2>&1 | grep yo` – Satō Katsura Jun 29 '16 at 17:04
  • @SatoKatsura That works! Thank you. You can provide it as an answer and I will accept it, or I can do it. I small explanation of why that works would be great, too. – Raine Revere Jun 29 '16 at 17:06
  • I am guessing that it directs stderr to stdout, which is what grep uses? – Raine Revere Jun 29 '16 at 17:07
  • 1
    Yes, you want to `grep` the error messages from `less`, and `less` prints error messages to `stderr`. – Satō Katsura Jun 29 '16 at 17:11
  • 1
    See [here](http://unix.stackexchange.com/a/38691/117516) for a better way to find broken symlinks. – Satō Katsura Jun 29 '16 at 17:13
  • Since we're talking about odd ways of doing things, `cat` might be easier... `cat * > /dev/null` will send the results to stderr. If you want to catch it in a variable, `badlines=$(cat * 2>&1 >/dev/null) ; echo "$badlines"` – Stephen Harris Jun 29 '16 at 17:14

2 Answers2

2

The wildcard has nothing to do with grep, all that grep sees is what is piped to it. The wildcard is expanded by the shell and the list of files it expands to is passed to less. So the issue has nothing at all to do with grep.

That said, if you're looking for broken links, you can do:

for f in /Users/raine/.nvm/versions/node/v5.5.0/lib/node_modules/*; do
     [ -e $(readlink -f "$f") ] || echo "$f"; 
done

That will iterate over all files and directories in /Users/raine/.nvm/versions/node/v5.5.0/lib/node_modules/, check if their target exists (readlink will print the file name iot was run on if that file isn't a link) and print the name if it doesn't.


A much better solution I just learned about is:

find /Users/raine/.nvm/versions/node/v5.5.0/lib/node_modules/ -xtype l 

The -xtype will test whether the target of the link is, in this case, a link, so it will only be true for dangling links.

terdon
  • 234,489
  • 66
  • 447
  • 667
  • Thank you. I changed the OP to reflect the real question now that I understand it. Your answer is helpful, though I will go with `2>&1` as the accepted answer since it clears up my fundamental misunderstanding. – Raine Revere Jun 29 '16 at 17:19
  • 1
    @Raine in that case, please post the answer yourself and accept it so the question can be marked as answered. – terdon Jun 29 '16 at 17:21
  • `find -L /Users/raine/.nvm/versions/node/v5.5.0/lib/node_modules/ -type l` – Costas Jun 29 '16 at 17:29
  • @Costas `find -xtype l` is safer for reasons explained [here](http://unix.stackexchange.com/a/38691/22222). – terdon Jun 29 '16 at 17:31
  • I see now. Thanks. So for such security reason we have to add `-path '/Users/raine/.nvm/versions/node/v5.5.0/lib/node_modules/*'` – Costas Jun 29 '16 at 17:45
  • @Costas I guess so yes, I'm only learning about all this now myself. I think using `-xtype l` is much simpler though. As long as your `find` supports it, it's not POSIX. – terdon Jun 29 '16 at 17:48
1

As @SatoKatsura pointed out in their comment, the (hacky) use of less is outputting to stderr, while grep reads from stdout. Though it is a poor solution to the actual task of finding dead symlinks, it can work by redirecting stderr to stdout:

less ~/.nvm/versions/node/v5.5.0/lib/node_modules/* 2>&1 | grep "Not a file"
Raine Revere
  • 190
  • 1
  • 11