2

I want to make ls and cd to first or second directory it shows, whatever name the first one or the second would be (dir1 or dir2, in this case):

$ ls { + some command like | grep which would get me to dir1 or dir2 or any other dir I want to }
dir1 dir2 dir3 dir4

Is it possible?

UPDATE:

I want to do that in the terminal without creating an external script.

5
  • 1
    I think I'm missing something. From your example (four directory names being returned) what do you want to actually happen?
    – Oli
    Aug 16, 2013 at 12:04
  • I got the first or second directory. Aug 16, 2013 at 12:05
  • I still don't understand what you're asking. Are you asking for something to just show you the first two directories?
    – Oli
    Aug 16, 2013 at 12:07
  • Okay so now grep is involved. We're filtering... What's the input and what's the desired output? Why are we selecting "dir1 or dir2"? Because they're first?
    – Oli
    Aug 16, 2013 at 12:11
  • @Oli please look at my answer once. I need your help to fix the final part.
    – Raja G
    Aug 16, 2013 at 12:13

5 Answers 5

3
ls | head -n 1 && cd "$(ls | head -n 1)"

will do the job for first directory. For second directory, use:

ls | awk 'NR==2' && cd "$(ls | awk 'NR==2')"

For n-th directory, you can use:

ls | awk 'NR==n' && cd "$(ls | awk 'NR==n')" #change n with the wished line number.
2

I would do

alias cd1='cd "$(printf %s\\n */ | sed q)"'
alias cd2='cd "$(printf %s\\n */ | sed -n 2p\;2q)"'

and similar, but you can have problem if there is not one or two sub-directories.

1

I just made this up:

#!/bin/bash

dir_counter=0

for i in *; do
    echo "Checking "$i"";
    if [ -d "$i" ]; then
        echo "$i is a directory"
        let dir_counter=dir_counter+1
        if [[ "$dir_counter" == 2 ]]; then
            cd "$i"
            #inside of $i now
            #do whatever you like
            pwd
            exit 0
        fi
    else
        echo "$i is NOT a directory"
    fi
done

I don't know if it is the best way to accomplish what you want.

Usage:

alex@MaD-pc:~$ ls
a                  Desktop    Downloads  gsettings_source  nitroshare  Qt             Templates  Wallch.DEB.Build
annoying_file.txt  Documents  Dropbox    Music             Pictures    second_dir.sh  Videos
alex@MaD-pc:~$ ./second_dir.sh 
Checking a
a is a directory
Checking annoying_file.txt
annoying_file.txt is NOT a directory
Checking Desktop
Desktop is a directory
/home/alex/Desktop
alex@MaD-pc:~$

The script will just cd on the 2nd directory that it will find. Just keep in mind that this will not work for hidden directories.

1

I have written some script for you but this is not a complete answer to your question but I am sure it will help you though. I can list your first directory with my command.

ls | head -n 1 |awk '{print $1 }'

I am not sure how to change to directory then. I have taken your example.

jai@frank-Jai:~/sandbox$ ls | head -n 1 |awk '{print $1 }'
dir1
jai@frank-Jai:~/sandbox$ ls | head -n 2 |awk '{print $1 }'
dir1
dir2
jai@frank-Jai:~/sandbox$ 

we can list as many directories as we want.

9
  • @Oli , how to cd to the output that script which can list directories ?
    – Raja G
    Aug 16, 2013 at 12:08
  • 1
    yes, this is not complete, but close to what I want. "cd" remains. Aug 16, 2013 at 12:12
  • yes I am thinking , you also try . :)
    – Raja G
    Aug 16, 2013 at 12:12
  • how do I print only the second or the third directory (or any other I want to)? Aug 16, 2013 at 12:13
  • 2
    Parsing the output of ls is often precarious. Aug 16, 2013 at 12:14
1

I am slightly unsure as to what you want really, but I interpret your question as wanting a 'one-liner' that captures a list of directories in $HOME, for example, and then enables you to cd to the first or second directory in that list, or any of them for that matter.

This I think is possible if you place all the directories in an array and then you could cd to any directory in that array, by using, for example, cd "${cdarray[1]}", which would actually take you to the second directory in the list, because Bash arrays always start at 0, so index 0 in the array is actually the first directory.

Here's the one-liner I created that you can use; modify it to suit your purposes. I exclude directories from the list that are actually symbolic links ( [[ ! -L "$d" ]] ). You can remove this test if you need to include them and just keep the test for the directory.

This is an example for the $HOME directory, and I have added $HOME to the command, so the paths are now absolute, so you will be able to later run cd "${cdarray[1]}" as a separate command from any location and it will work. If you create it for another directory, just specify that absolute path instead of $HOME in the command below, unless of course you want it to work only relative to the directory in which it was created.

cdarray=(); for d in *; do [[ ! -L "$HOME/$d" && -d "$HOME/$d" ]] && cdarray+=("$HOME/$d"); done; cd "${cdarray[1]}"

Now, any directories with spaces in their names will be handled successfully.

The indexed array is declared, and then if the found item is a directory and not a symlink, it is added to the array and then after the semi-colon we cd to the directory we want, e.g. cd "${cdarray[1]}".

You could add || exit 1 at the end if you used this in a script, but I didn't add that above as it would close the interactive terminal if the cd command failed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .