How can I make shell autocomplete the beginning of a filepath? - bash

I have a project with a deeply nested folder structure. Most of the time I know the name of the file I want to work with, but the folder path is too long/complicated to type when I want to edit it, like:
vim folder/is/deep/down/there/myfile.js
Is there a way to make the shell auto populate the path for me if the filename is unique, with something like:
vim *myfile.js
press TAB -->
vim folder/is/deep/down/there/myfile.js
I mostly use bash, but I'm fine with zsh if it can solve the problem.

I think this is what you're looking for, vim will open all instances of myfile.js in the directory. Fish shell will allow me to tab through the different matching files but I'm not sure it that works with bash.
vim **/myfile.js

What could be a good idea would be to use locate utility in a bash script.
Calling your bash script passing filename as argument would be a smart move, and then using the previously named utility to find it.
Having done that you could simply find if there was 1 or more matches, and if there's just a match you can just use vim [match].
And obviously, the script could be called like ./openinvim.sh myfile.js

Related

Add Path to OSX to El Capitan

I am trying to learn UNIX.
I am using a book called “Wicked Cool Shell Scripts”.
I am told that .bash_profile contains my login for bash and that I can add paths to it so that commands I enter in Terminal will find the scripts I am writing.
The contents of my current bash_profile is:
export PATH=~/bin:$PATH
When I type echo $PATH I get:
/usr/local/opt/php#7.0/bin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/3.3/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin
I would like to add a path so that - as the book suggests - I can write scripts and refer to them directly from the command line, instead of having to constantly navigate to that directory to run them.
I have a file with a shebang. It runs fine when I type its name and am in the same directory. I have moved that file to the folder scripts, which is located under crg/Users/ (ie: Users/crg/scripts)
According to this book, I can now alter my $PATH to include that directory, so that when I type that filename, the program will run.
I cannot do this successfully.
I don’t know why.
After every edit, I quit terminal and reopen it, to ensure it is using the newly edited bash_profile.
As per the books instructions on page 5, I have tried entering this in my bash_profile:
export PATH=”/Users/crg/scripts/:$PATH”
I save my bash_profile, quit Terminal, reopen it and type echo $Path
This is the result:
”/Users/crg/scripts/:??
This is not right. In fact, it's wildly wrong. And it does not allow me to run scripts from the folder indicated. It also seems to completely overwrite whatever was in the bash_profile before this, so I cannot - after doing this 'simple edit' suggested by a 'professional' - run a php -version command from the Terminal.
I am at a complete loss as to why this is happening.
Why is there a quotation mark at the beginning of this line (but not at the end)?
What's with the colon and the 2 question marks at the end of this line?
How do I add/append a path to my bash_profile?
More questions:
When I try and solve this on my own using “the Internet”, I discover many interesting versions of this ‘simple’ process: Here’s one suggested by a ‘professional’:
export PATH="${PATH}:/path/to/program/inside/package"
This is very different from what the book says...
Here’s another version of ‘how to do it’ by ‘a professional’:
export PATH=$PATH:/usr/local/sbin/modemZapp
Notice that this one doesn’t even have quotes. In both, the PATH variable comes before the actual path.
Why are there so many 'versions' of how to perform this simple task?
Can someone please tell me how to add a path to my .bash_profile?
UPDATE: I have followed the advice here, (add it to etc/paths) but this does not work either.
I get the exact same thing when I type echo $PATH in a new Terminal:
/usr/local/opt/php#7.0/bin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/3.3/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr:/usr/local/share/npm/bin:/Users/fhb/scripts:/opt/X11/bin
I can't help but note a comment on that last page: "I have been through at least a dozen different methods for adding directories to $PATH. Why are there so many and why do so few of them work?"
To answer your first question if you look closely your quotes are ” instead of ". I'm guessing you edited either your bash_profile or this post in a rich text editor instead of a plain text one. I would recommend notepad for Windows or nano for *nix if you are writing code. To fix this issue, replace the ” with ".
To answer your second question, bash is quite forgiving and will allow you to set a string variable in multiple different ways, even without quotes. However you can run into issues when a string contains whitespace, for example: /Users/lilHenry/my scripts.
The "${PATH}" syntax is just another way to declare a string. It has the benefit that it allows you to interpolate variables into a string like so:
prefix="foo"
echo "${prefix}bar"
This will output foobar, whereas echo "$prefixbar" will not output anything as the variable prefixbar has not been set. I would suggest sticking with the export PATH="/Users/me/bin:$PATH" syntax.

How do I map a certain input in bash to a command?

So I was wondering if it is possible for me to map a certain input to a command in gnome terminal. For example, when I type "foo" in the command shell, it would automatically execute a certain command like going to a directory where a program is located and execute that program in a specific configuration.
Yes, it is called an alias:
A Bash alias is essentially nothing more than a keyboard shortcut, an
abbreviation, a means of avoiding typing a long command sequence. If,
for example, we include alias lm="ls -l | more" in the ~/.bashrc file,
then each lm [1] typed at the command-line will automatically be
replaced by a ls -l | more. This can save a great deal of typing at
the command-line and avoid having to remember complex combinations of
commands and options. Setting alias rm="rm -i" (interactive mode
delete) may save a good deal of grief, since it can prevent
inadvertently deleting important files.
So basically:
alias foo="cd /path/to/dir; ./myprogram; cd -"
cd - is following #Cyrus's suggestion - to return you to the directory you started from. This is safer and more expected of most commands, but of course, you can use whatever you like.

Bash alias autocompletion that considers only *.foo files

Whenever I want to start editing my LaTeX sources by launching, e.g., the command vim pdeOptAff.tex, I find that bash the (tab)-autocompletion is still tedious because the folder typically contains a bunch of files with the same name but different endings:
$ ls
pdaeOptAff.aux pdaeOptAff.out pdaeOptAff.tex.latexmain
pdaeOptAff.bbl pdaeOptAff.pdf pdaeOptAff.toc
pdaeOptAff.blg pdaeOptAff.synctex.gz
pdaeOptAff.log pdaeOptAff.tex
Since I always want to open the the ~.tex file, I would love to have a filter that makes autocomplete expand only the ~.tex files.
In addition, I have an alias defined: alias g='gvim --remote-silent'. So this filter, in particular, should work for the alias.
Try:
complete -f -X '!*.tex' g
Then, you can type:
g <TAB>
And get the completions. Note: this doesn't complete directories. Someone else may have a better solution using compgen.
There's a helpful autocomplete guide on The Linux Documentation Project too.

bash tab completion filter out options

I would like to make tab completion in bash a bit more intelligent.
Let's say I have a folder with a src file .lisp, and a compiled version of that file .fasl. I would like to type vi filename [tab tab], and the .lisp autocompletes as the only option. That is, it's not likely that I want vim to open a compiled binary, so don't have it in the list of autocomplete options to cycle through.
Is there a way that I can keep a flat list of extensions that autocomplete ignores, or somehow customize it for vim, so that autocomplete ignores only particular file extensions when a bash command starts with vi ...
Any ideas are appreciated.
Thanks!
From man bash:
FIGNORE
A colon-separated list of suffixes to ignore when performing
filename completion. A filename whose suffix matches one of the entries in FIGNORE is excluded from the
list of matched filenames. A sample value is ".o:~" (Quoting is
needed when assigning a value to this variable, which contains
tildes).
So, for your example this can be set in your .bashrc file with
FIGNORE=".o:~:.fasl"
or, if you want to keep any other site-wide settings:
FIGNORE=".o:~:.fasl:$FIGNORE"
The bash complete command seems to be what you want.
Here is a Linux Journal link to 'complete' command video. and here is the follow-up page More on Using the Bash Complete Command
The links explain it quite well, and here is a related SO Question/Answer: Bash autocompletion across a symbolic link

Can I use what I wrote on the shell (bash, cmd, irb, etc) in a script automatically?

The general idea is pretty simple, I want to make a script for a certain task, I do it in the shell (any shell), and then I want to copy the commands I have used.
If I copy all the stuff in the window, then I have a lot of stuff to delete and to correct. (and is not easy to copy from shell)
Resume: I want to take all the things I wrote...
Is there an easy way to do this easy task?
Update: Partial solution
In bash, the solution is pretty simple, there is a history command, and there are ports of the idea:
IRB: Tweaking IRB
Cmd: Use PowerShell -> Get-History (or use cygwin)
Another Update:
I found that doskey have a parameter history to do this:
cmd: Doskey /history >> history.cmd
Yes, you can use:
history -w filename.sh
This will save your command history to filename.sh. You may need to edit that to keep just the lines at the end that are part of your command sequence.
NOTE: This is a bash command and will not work with all shells.
script may help here. Typing script will throw you into a new shell and save
all input and output to a file called typescript. When you're done with your interaction,
exit the shell. The file typescript is then amenable to grep'ing. For example, you might
grep for your prompt and save the output to the file. If you're a clumsy typist like me, then you may need to do some cleanup work to remove backspaces. There used to be a program that did thisbut I don't seem to find it right now. Here is one I found on the
'net: http://www.cat.pdx.edu/tutors/files/fixts.cpp
This approach is especially useful if you want to track and post on the web an entire interactive session.

Resources