Zsh: tab completion for files not in the current directory? - zsh

I'm new to zsh and I'm trying to figure out how to get tab completion to work so that when I typed part of the name of a file that's not in the current directory zsh will complete it.
The idea is that I have some scripts in ~ and c:\MyStuff\bin and I'd love for zsh to try and complete those (executable) scripts when I'm in other directories.
Being able to complete files that are anywhere in my path would be nice, but if it's easier to complete files using a list of directories set in my .zshrc, well, that would work fine too.
If anyone has any pointers for resources about how to do this, or even advice like "This will / won't work in zsh" that would be great. zsh seems open-ended enough that it ought to be able to do this AND ALSO I've searched long enough without finding anything that I wouldn't be surprised if there's nothing at the end of this rabbit hole :)
Thanks in advance!

So I decided to invest the time and actually try and read the (very, very thorough) zsh completion docs. There's a lot there, including a section which says that zsh actually does this out of the box:
8 Command Execution
"...the shell searches each element of $path for a directory containing an executable file by that name..."
Turns out this does work for me, it just takes a long time (more than a second or two) and so I thought it wasn't working.
Next up: looking at why it's taking so long - perhaps it's my very long $path variable :)

Related

R Working Directory "cannot change"

Working Direcotry Cannot Change It's saying that there's an error in my code but I've tried it multiple times with countless variations on the code (I wiped my past attempts sorry) and it refuses to change the working directory. It won't change to other things either so it's not just this folder. What's the issue?
This probably means that the directory you want to change to does not exist. From the image I think you are using Windows, in which case the proper path to the directory would look like this:
setwd("C:/Users/$USER$/Desktop/r-novice-inflammation"
Change the $USER$ to your own username and it should work.
Paths always start with the letter of the hard drive in Windows. The easiest way to find the proper path to a directory is, in my opinion, to right click on the folder and look for the "Location" in properties. The IDE RStudio has a menu which you can use to change the working directory, which may be easier than using vanilla R.
The exception is setwd("~") which links to the Documents folder of your current user (i.e. C:/Users/$USER$/Documents). Based on the comments I realised that other commands such as setwd("..") (i.e. one folder up in the hierarchy) can be combined with ~ which explains what you are doing. In this case the following works for me:
setwd("~/../Desktop/")

Why the command “grep” doesn’t work with no parameters?

I’ve been trying to use the command grep, but without the -R parameter the whole cli goes just idle.
Can someone explain me why?
I assume you're not providing any files at all to search. If that's the case, then grep is reading from stdin (standard input). It's waiting for you to close the input (Ctrl+D), and then it'll search that.
If you want to search files, you need to tell it what files to search. Perhaps you mean to include * in your command?

find ~/Desktop creek.jpg returns no such file or directory when creek.jpg is on my desktop. Why?

I am learning the linux utility find and am finding the man page difficult to read. I have defaulted to testing the command and seeing what it does.
I have a file called creek.jpg on my desktop.
When I type
find ~/Desktop creek.jpg
It appears to print out every file in my desktop, then prints out
find: creek.jpg: No such file or directory
Here is my mental picture of how find is working. In the man page, it says finds job is to "walk a file hierarchy." Here is my mental image of how find works. A file hierarchy (also referred to in the man page as a directory tree.) is like an oak tree. Each fork in the tree is a directory. Each leaf or acorn on the tree is a file. Find is a hyperactive squirrel that scrambles up and down the tree, touching every leaf, acorn, and branch.
Since the first line of the man page says that find's job is to walk a file hierarchy, apparently find's main job is to not, as I first thought, to actually find stuff. Instead, its job is to scramble up and down the tree, visiting things. A side effect of visiting things is that you can tell it to look for things and it will tell you if it sees them.
Apparently I am failing at two parts: how to tell it to look for creek.jpg on my desktop, and how to tell it to NOT tell me about every last little branch and leaf it touches with it's excited squirrely paws.
So:
When I type the above command, why is it telling me everything it is visiting, and why is it telling me it did NOT find creek.jpg?
How do I get it to find creek.jpg?
How do I get it to NOT tell me every other file it visited on it's "walk of the file hierarchy"?
You have provided two paths (~/Desktop and creek.jpg in current folder) and haven't provided any matching criteria. Try
find ~/Desktop -name creek.jpg
Try this: find ~/Desktop -name filename

UNIX - Renaming files with long names

I am screwed. I misused wildcards like a moron, in the rename command.
I repeated names twice in a 3gig folder, which I cannot afford to delete.
Now, the rename command is not working, and it says the file name is too long.
Please help me.
If programming can solve this, please let me know. I am a competent programmer in Java and PHP.
Under the hood, any rename command should get implemented with rename(). If you are in the directory where the file is and do:
mv hugefilenamethatiscreweduponandwanttobemuchshorted tersefile
it should work, as I don't think the path would get expanded out and overflow the limit. Otherwise, you can temporarily move the parent directory somewhere so it had a minimal path (like /p) and then rename the file and then move it back.

How to learn work effectively with Unix CLI

Do you know any resources that teach to good habits of working in UNIX command line?
EDIT: I don't mean general books about shell or man pages. I mean the things that you can only see watching professionals working with command line. For example when changing frequently between two directories they use "pushd" command, when repeating a command they use "history". I can read about these commands but I want to make it a habit to use them effectively.
I am speaking out of my own experience so it may not apply to you;
The best way to be efficient is actually using it on a daily basis, instead of using graphical tools even if they make look things easy. You will then become aware of most common tasks you care about, and instead of trying to grok it at once, you get a fairly good starting point to start learning. Man pages are the first thing to look at, but there will be non-obvious tricks which you need to search anyway. Knowing what you exactly want, infinitely increases probability of finding it.
For example, you can find how to search all mp3 files easier in man page of "find" than how to deal with files in general (where to start?).
Some common bash command line actions, not in order:
Command line editing: you'll want to be good with emacs or vi and apply that to editing your commands.
Completion: use TAB to expand file names and paths.
note: There is a huge set of file, command, and history completion functions, and it is configurable. Big topic.
"cd -" : go back to the last directory you were in
~ = home directory (or ~user for users home dir)
"ESC ." : expands to the final arg from the previous command
"!string" : execute the last command starting with string
learn find, grep, sed, piping "|" and redirection ">". You'll often combine these to do useful things.
Loops from the shell prompt, e.g. "for" loop - to do repetitive actions
Learn your regular expressions! Often used for matching files.
example: ls x[0-5]*.{zip,tar} = list files starting with x, followed by a number 0 through 5, followed by any string ending in .zip or .tar
If possible ask others for their favorite tricks, read the manual, and practice.
For the more advanced stuff This seems to be fairly comprehensive
this is a great resource: "Rute User's Tutorial and Exposition" (http://rute.2038bug.com/index.html.gz)
stackoverflow.com esp. the bash tag ;-)
(and of course the bash man page)
If you want things that you can "only see watching professionals working with command line," then you've answered your own question: Watch professionals working with the command line. I don't personally find that very useful unless the other person is doing the same thing multiple times; it's hard to pick something up after just one session because it's hard to watch the screen and the keyboard at the same time.
I think the key is to not try to become an expert right away. Just use the command line frequently, and be aware that you might not be using it as well as you could, but don't let that discourage you from using it anyway.
Browse through the man page of your shell, and through lists of tips, not with the goal of memorizing everything in them, but just to pick out a couple of things to try out. Skim through until something catches your eye and makes you think, "Gee, that sounds useful." Then try it out. Not everything is going to be useful immediately; you might have to wait a while before you encounter a situation where you can try something out. Maybe you could write down some things on Post-It notes by your desk to remind you that certain feats are possible, so when you encounter a situation where a more obscure feature could be handy, you'll be more likely to remember to try it.
Frankly, it's impossible to learn this stuff in a vacuum. You need to have problems to solve.
While it certainly helps to have familiarity with the tools available (of which there are a myriad), "learning" it requires applying it. And applying it requires "real" problems to solve.
For example, the skillset of a System Admin may be different from someone who works with databases because their roles are different.
I use them for data processing, using mostly one off files. /tmp/x.sh and /tmp/x.x are worn bare in the directory folder.
My hammers tend to lean towards: ls, find, sort, sed, vi, awk, grep, and comm. Combined with simple shell scripting like: for i in cat /tmp/list; do .. done
But I do a lot of ETL work, and very few script files, which is why my shell scripting skills are so weak.
I do rely on one script, however:
#!/bin/sh
# latest -- show latest files
ls -lt $# | head
As 95% of the time the files I'm working on are in the top 10 latest files. And "latest *.txt" works a peach.
So, bottom line, you need problems to solve. You need to learn the 'man' command, man -k is nice to find things. You also need to leverage the "See Also" at the bottom of most man pages. That's a treasure trove of "I didn't know you could do that".
Then, just start solving problems. Start figuring out "what would be nice to have" and then see if it exists (it very well may). If not, awk, perl, or python can make those "nice to haves" out of thin air.
Join a LUG. That is where I learned most things early on. Ask the organizers to do a "Bash Tips And Tricks Night".
Deft shell users love to show off.
apropos is a really good tool for this sort of thing. Whenever you find yourself unsure of the best way to do something, or wishing you weren't repeating yourself, just use apropos with a keyword or two to find other commands that can help. In distros like debian, you can also install web-based help tools that search all of the manuals available on the system: texinfo, man pages, html, and pdf etc.
Aside from that, yep, read your shell's manual right through at least once --- preferably, go back to repeatedly it as you learn more, reach limits and want to be more efficient.
The join a LUG idea is also good; you'll definitely learn from others' demos.

Resources