Bash tab completion like ncftp? - linux

In ncftp tab completion only shows the differences of matched files. E.g. with the following files
file123 file125 aa
then typing ls fil will first complete to ls file12 and show
3 5
Question
Can the same be done in Bash?

BASH supports tab-completion which is fairly robust. It is implemented through bash_completion. However, be aware that the way bash_completion is configured will depend on what options are set by default by your distribution. As for its basic functionality, it is exactly as you describe for ncftp. When a partial name is entered on the command line and tab is pressed, then a list of name-matched files are displayed. Once you have entered enough characters to make the name unique, tab will complete entry of the unique filename on the command line.
Linux also provides ls, but its behavior is not the same as you describe for ncftp. ls will return the names of files and directories that match the pattern you specified. By default, the name you provide to ls is not expanded. Meaning if you have file123 and file125 in a directory and issue the command ls file, you will be greeted by the error ls: cannot access bash: No such file or directory. But providing a wildcard (filename globbing) with ls file* will return both names.
If you have additional specific questions. Just leave a comment and we will do our best to help.

Related

Linux command select specific directory

I have only two folders under a given directory. Is there any method to choose the second directory based on the order and not on the folder name?
Example: (I want to enter under doc2)
#ls
doc1 doc2
If you really want to use ls,
cd "$(ls -d */ | sed -n '2p')"
selects enters the second directory listed by it, independently of the number of directories provided by ls.
Parsing ls output is not a good idea generally, although it will work in most cases and will cause no harm if you are just using it in your interactive shell for fast navigation. You should not use this for serious programming.
You can use the tail command to get the last line
ls |tail -1

RH Linux Bash Script help. Need to move files with specific words in the file

I have a RedHat linux box and I had written a script in the past to move files from one location to another with a specific text in the body of the file.
I typically only write scripts once a year so every year I forget more and more... That being said,
Last year I wrote this script and used it and it worked.
For some reason, I can not get it to work today and I know it's a simple issue and I shouldn't even be asking for help but for some reason I'm just not looking at it correctly today.
Here is the script.
ls -1 /var/text.old | while read file
do
grep -q "to.move" $file && mv $file /var/text.old/TBD
done
I'm listing all the files inside the /var/text.old directory.
I'm reading each file
then I'm grep'ing for "to.move" and holing the results
then I'm moving the resulting found files to the folder /var/text.old/TBD
I am an admin and I have rights to the above files and folders.
I can see the data in each file
I can mv them manually
I have use pwd to grab the correct spelling of the directory.
If anyone can just help me to see what the heck I'm missing here that would really make my day.
Thanks in advance.
UPDATE:
The files I need to move do not have Whitespaces.
The Error I'm getting is as follows:
grep: 9829563.msg: No such file or directory
NOTE: the file "982953.msg" is one of the files I need to move.
Also note: I'm getting this error for every file in the directory that I'm listing.
You didn't post any error, but I'm gonna take a guess and say that you have a filename with a space or special shell character.
Let's say you have 3 files, and ls -1 gives us:
hello
world
hey there
Now, while splits on the value of the special $IFS variable, which is set to <space><tab><newline> by default.
So instead of looping of 3 values like you expect (hello, world, and hey there), you loop over 4 values (hello, world, hey, and there).
To fix this, we can do 2 things:
Set IFS to only a newline:
IFS="
"
ls -1 /var/text.old | while read file
...
In general, I like setting IFS to a newline at the start of the script, since I consider this to be slightly "safer", but opinions on this probably vary.
But much better is to not parse the output of ls, and use for:
for file in /var/text.old/*`; do
This won't fork any external processes (piping to ls to while starts 2), and behaves "less surprising" in other ways. See here for some examples.
The second problem is that you're not quoting $file. You should always quote pathnames with double quoted: "$file" for the same reasons. If $file has a space (or a special shell character, such as *, the meaning of your command changes:
file=hey\ *
mv $file /var/text.old/TBD
Becomes:
mv hey * /var/text.old/TBD
Which is obviously very different from what you intended! What you intended was:
mv "hey *" /var/text.old/TBD

Unable to list all files in $HOME directory

I installed the latest version of cygwin and wanted to list all files in my $HOME direcrory (in paticular .vimrc config file). I type ls -l and see 0 files, but when I try to open the file via vim it's ok. Actually (after 2 TABs):
what's wrong?
In *nix systems, prefixing a name with . causes the item to be hidden.
To include these files when you type ls -l, you will need to include the -a modifier.
You can write this as ls -la for brevity, if you like.
In the future, if you're having trouble with a program, you can type (e.g.) man ls to open the manual pages for (e.g.) ls.

Quickly accessing file names listed by the ls command on Linux shell

I am working on the Linux shell, and I usually have to deal with files that have complicated names. For example, I list the files of the current directory using ls:
MOD11A1.A2012193.h12v03.005.2012196013543.hdf
MOD11A1.A2012193.h12v04.005.2012196013541.hdf
MOD11A1.A2012193.h12v05.005.2012196013541.hdf
And then, if I need to open one of them, I would write:
vim MOD11A1.A2012193.h12v03.005.2012196013543.hdf
The way I do it, is by first selecting the file name from the list provided by ls, right click, copy it, right click, paste it after vim.
Is there a shorter way to do this?
Use wildcard expansion, i.e. for the second file:
vim *v04*41*
or, if your shell supports it, tab-completion:
type vim M; press [Tab], that completes all up to next difference, i.e. OD11A1.A2012193.h12v0; type 4; press [Tab], and so on.
If you would like open first of hdf files then use:
vim `ls -1 *.hdf | head -n 1`
ls-1 - minifies dump to just a name per row
head -n 1 - selects first item only

How to do partial search in Linux with locate?

I prefer to seach with locate command but I don't know how to perform a partial search with it.
Suppose I want to search file containing the word libevent. How can I do that?
Locate searches for file names. Not file contents.
The ugly way is to use grep It'll start searching from / directory.
grep -irn 'libevent' /
The better way is to narrow down the suspected directories where this files could exists. Suppose those directories' full paths are /path/to/dir1, /path/to/dir2 etc. Then invoke the following command.
for dir in /path/to/dir1 /path/to/dir2
do
grep -irn 'libevent' $dir
done
The locate command is not searching inside the content of files like grep (and other commands) do. It is simply searching inside file paths.
locate work by using a cache index of file paths, and this index is often updated by the updatedb utility.
addenda
A useful way to search some pattern inside (the content of) some files is to use the ability of zsh or some recent versions of bash to expand the ** file pattern, like e.g.
grep foo ~/gee/**/*.[ch]
with zsh this search inside all files named *.c or *.h under $HOME/gee/ containing foo. I find this feature tremendously useful, and justifying alone the adoption of zsh as my interactive shell. With other shells you might type the much longer
find $HOME/gee -name '*.ch' | xargs grep foo

Resources