0

I added Notepad++ to Cygwin. I'd like to be able to find files and open them with one single command, I think about something like this:

npp $(grep -l -r 'phrase')

The problem is that it seems not to be able to open files which have spaces within names... :( Could this command may be modified to do the job?

2 Answers2

0

grep -l separates filenames with a newline. You need to see newline as an argument splitter, and not to split on ordinary space.

Also, when generating a list of files you want to operate on, xargs is in order.

$ grep -l -R 'regex' | xargs -d '\n' npp

If your filenames may have a newline in them (yeah, unlikely on windows), use null as the separator:

$ grep -l -R -Z 'regex' | xargs -0 npp

Less typing, and more general to boot.

bobbogo
  • 14,989
  • 3
  • 48
  • 57
  • Thank You. My test files have "ico" text inside. If I use: `$ grep -l -R 'ico' | xargs -d '\n' npp` I get: `xargs: npp: No such file or directory` – Thomas Leigh Oct 08 '19 at 12:30
  • Just what the error says: _xargs_ cannot see a command call _npp_. Is _npp_ on your `$PATH`? Is it an alias? What does `$ type npp` say? – bobbogo Oct 08 '19 at 12:42
  • > "Is npp on your $PATH? Is it an alias?" To * .baschrc* file (home directory) I added: `npp () { /cygdrive/c/Program\ Files/Notepad++/notepad++.exe -multiInst -nosession -noPlugin $(cygpath -w -- "$@") }` > "What does $ type npp say?" `npp is a function npp () { /cygdrive/c/Program\ Files/Notepad++/notepad++.exe -multiInst -nosession -noPlugin $(cygpath -w -- "$@") }` – Thomas Leigh Oct 08 '19 at 12:52
  • Aliases and shell functions only work inside _bash_. _Xargs_ requires an actual command. So make your _npp_ a shell script, and put it in a folder on your `$PATH`. There exist other options too, but they don't fit in a comment! – bobbogo Oct 08 '19 at 12:56
  • > "make your npp a shell scripts and put it on your $PATH" Would You be willing to point out how to do this? I'm a beginner in this field, I can do the research on how to make "shell scripts", but I don't know what I should put on My "$PATH". – Thomas Leigh Oct 08 '19 at 12:59
  • That's a different question! Just put the commands into a file `npp`. Put `npp` into a folder where you might put other commands (`~/bin/` say (i.e., the `bin/` folder in your `$HOME` directory)). Ensure that folder is on your `$PATH` — put `PATH=~/bin:$PATH` in your `~/.bash_profile` maybe. – bobbogo Oct 08 '19 at 13:03
  • I put npp code snippet into "npp" file (~/bin). Within .bash_profile file I found this: `# Set PATH so it includes user's private bin if it exists # if [ -d "${HOME}/bin" ] ; then # PATH="${HOME}/bin:${PATH}" # fi` and removed three last "#". I also removed npp code snippet from .baschrc. Cygwin relaunched and npp gives `bash: npp: command not found` – Thomas Leigh Oct 08 '19 at 14:03
  • Interestingly, when I do the same command inside the main Cygwin window, I get: `$ npp /home/Thomas/bin/npp: line 1: syntax error near unexpected token `$'{\r'' 'home/Thomas/bin/npp: line 1: `npp () { ` I changed the "npp" file content into `/cygdrive/c/Program\ Files/Notepad++/notepad++.exe -multiInst -nosession -noPlugin $(cygpath -w -- "$@")` and now it opens Notepad on "npp" - but only within the main Cygwin window. If I switch to another directory within Cygwin window, "npp" gives: "npp: command not found ". – Thomas Leigh Oct 08 '19 at 14:03
  • _Cygwin relaunched and npp gives bash: npp: command not found_: `$ type npp` will tell you what _bash_ makes of the command (obviously not found). `$ tr : \\n <<<$PATH` will print out your `$PATH` nicely. Is your ~/bin/ folder on the list? Add it manually `$ PATH=~/bin:$PATH` and ensure `$ type npp` says `npp is /home/blah/bin/npp` (or somesuch) – bobbogo Oct 08 '19 at 16:02
  • _line 1: syntax error near unexpected token $'{\r'' '_ This may be due to the file having dos line endings. Run `dos2unix` or similar to ensure it has unix line endings. – bobbogo Oct 08 '19 at 16:06
  • > "ensure $ type npp says npp is /home/blah/bin/npp" Yes, it gives this message - but if I run _Cygwin_ from other directory, it gives that: `Thomas@Evelyn /cygdrive/d/x $ type npp bash: type: npp: not found` – Thomas Leigh Oct 08 '19 at 17:13
  • What on Earth does _but if I run Cygwin from other directory_ mean? – bobbogo Oct 08 '19 at 18:55
  • I have a directory on disk f. If I run _Cygwin_ by default (a _Cygwin_ desktop icon) and navigate to this directory (by "cd"), it works fine - I can initiate "npp" from this directory. But I use this ( https://stackoverflow.com/questions/18140240/autohotkey-script-to-open-command-prompt/55735367#55735367 ) to open _Cygwin_ automatically within a directory from Windows Explorer window. And if I launch _Cygwin_ this way - in the exact same directory as the one mentioned above - the "npp" command does not work. – Thomas Leigh Oct 08 '19 at 19:54
  • In each of those shells look at `$PATH`. `.bash_profile` is only sourced in _login_ shells. Likely those started with a `-l` parameter. – bobbogo Oct 09 '19 at 09:11
  • Main window: `Thomas@Evelyn ~ $ $PATH. -bash: /home/Kić: No such file or directory` The other window with custom directory: `Thomas@Evelyn /cygdrive/d/x $ $PATH. bash: /cygdrive/c/Windows/system32:/cygdrive/c/Windows:/cygdrive/c/Windows/System32/Wbem:/cygdrive/c/Windows/System32/WindowsPowerShell/v1.0:/cygdrive/c/Program: No such file or directory` Seems like there is problem with folders with spaces within their names (like "Program Files"). – Thomas Leigh Oct 09 '19 at 11:57
  • Here you asked _bash_ to expand `$PATH` and to try to execute the result as a command(!). Don't do that. Just print out the value of `$PATH`: `$ echo "$PATH"`. Or if you want it a bit neater: `$ tr : \\n <<<"$PATH"`. (Don't type in the `$` prefix — I just use it to indicate it's a command-line.) – bobbogo Oct 15 '19 at 11:16
0

It's worth writing up another way around this problem. Command substitution (that's the $() construct) splits the output of the command into separate arguments. It splits on the characters in the $IFS variable. By default, these are the three white-space characters space, tab and newline.

Since you are unlikely to encounter newlines or tabs in your filenames, one option is to tinker with $IFS, removing the space character.

$ IFS=$'\t\n'
$ npp $(grep -l -r 'regex')

I don't recommend you change your $IFS globally.

bobbogo
  • 14,989
  • 3
  • 48
  • 57
  • > "I don't recommend you change your $IFS globally." Why? (what place better than within this thread should I ask this question?) – Thomas Leigh Oct 08 '19 at 13:15
  • Other scripts are likely to rely on its default value, and it's extremely rare that scripts set `$IFS`. The idiom is that if you change it, you should change it back afterwards. – bobbogo Oct 08 '19 at 13:39
  • The _IFS_ command works until I close _Cygwin_ (even if I run _Cygwin_ as an admin). I've searched for _IFS_ file within _Cygwin_ folder, to no avail. But it's great it works at least temporarily :) . – Thomas Leigh Oct 08 '19 at 17:05
  • In this context, IFS is not a command, it's a shell variable. When you set it, it exists only in that _bash_ process. If it has the _export_ attribute it will be put in the environment of any new processes that that _bash_ starts. IFS is not usually exported. _bash_ responds to many variables. If you want IFS always to have a non-default value, then you will need to set it in the appropriate one of _bash_'s many start-up files. – bobbogo Oct 09 '19 at 09:15
  • Thank You for clarifying this. I need to _Google_ where the _IFS_ value is stored then :) . – Thomas Leigh Oct 09 '19 at 12:01
  • Normally scripts are happy with the default value of `$IFS` and never set or fiddle with it. Just occasionally a script will modify its local copy for its own internal reasons. – bobbogo Oct 15 '19 at 11:18