2

I am using Ubuntu server and I want to create BASH script that would help me to navigate through directories at ease.

I found this piece of code and I am using:

#!/bin/bash
cd ~/ftp/server/googledrive

prompt="Please select a file:"
options=( $(ls -1) )

PS3="$prompt "
select opt in "${options[@]}" "Quit" ; do
    if (( REPLY == 1 + ${#options[@]} )) ; then
        exit

    elif (( REPLY > 0 && REPLY <= ${#options[@]} )) ; then
        echo  "You picked $opt which is file $REPLY"
        break

    else
        echo "Invalid option. Try another one."
    fi
done

However it only lists the directories, each of them having a corresponding number. Is it possible to make it in such a way that I can actually navigate through my directories?

EDIT: Thank you the comments. I should have done this when I created the post.

By "actual navigation" I mean this: the main goal was being able to select a .zip archive and unzip it in a specific folder, thus the navigation part. So you would have to navigate from Directory A to B and then to C. Starting from the first directory you would have all the directories listed and each of them having an unique number, by selecting a number you would then navigate to that specific directory. This would repeat until you would find the directory you need and then select an option like "Unzip here".

GMBeniamin
  • 109
  • 2
  • 12
  • 1
    See [Why you shouldn't parse the output of `ls`](http://mywiki.wooledge.org/ParsingLs). Much safer to have `options=( * )` – Charles Duffy Mar 29 '18 at 22:54
  • ...speaking to the question, though: What do you mean by "actually navigate"? Do you mean you want a curses-style interface? Then you should use something like `dialog`. Do you just mean you want your code to `cd` into the directory you select, *and leave your shell in that new directory when it exits*? Then you'll want to see [Why doesn't `cd` work in a shell script?](https://stackoverflow.com/questions/255414/why-doesnt-cd-work-in-a-bash-shell-script). – Charles Duffy Mar 29 '18 at 22:54
  • ...and if you *do* want a curses-style tool to navigate a directory tree, is there a reason you're writing your own rather than using something that already exists? I know of at least three. (All of them either work by creating a new and different shell instance in the target directory, or being wrapped in / implemented as a shell function, as a program can't change the working directory of the separate process that started it without that process's participation). – Charles Duffy Mar 29 '18 at 22:56
  • Have a look [there: How do I prompt...](https://stackoverflow.com/questions/226703/how-do-i-prompt-for-yes-no-cancel-input-in-a-linux-shell-script/27875395#27875395) – F. Hauri Mar 29 '18 at 23:04
  • Thank you for your answers! I am a newbie bash programmer and I truly appreciate your help. I edited my post so you know exactly what I need to do. – GMBeniamin Mar 29 '18 at 23:04
  • 2
    Do something like `while :; do options=( * ); select ...` for your outer loop. Then put in a `if [[ -d "$REPLY" ]]; then cd "$REPLY" || echo "Unable to access directory $REPLY" >&2; elif [[ -f "$REPLY" ]]; then unzip "$REPLY"; break; fi`, or whatever, inside your relevant `if` branch. Point being every time through the loop, you're potentially in a different directory per the instructions you got from the user, so your glob expands to a different list. – Charles Duffy Mar 29 '18 at 23:08
  • BTW, code formatting is only for *code* -- "Ubuntu server" is English text, not code; no need to put it in backticks. See discussion on Meta at https://meta.stackexchange.com/questions/135112/inline-code-spans-should-not-be-used-for-emphasis-right – Charles Duffy Mar 29 '18 at 23:10
  • Thank you for the comments. I will try everything you wrote and I am sorry for not following the guidelines regarding text formatting. – GMBeniamin Mar 29 '18 at 23:19

3 Answers3

2

Just a simple example to give you some ideas. Entering the number of a directory enters it. Hitting Ctrl+D pops back up a level.

#!/bin/sh

function selector {
    select name in *; do
        if [ -d "$name" ]; then
            cd "$name"
            selector
            cd ..
        fi
    done
}

selector
Developer Guy
  • 2,012
  • 6
  • 17
  • 30
CrazyApe84
  • 173
  • 5
  • Thank you for your answer! I followed your solution and also the comments and I finally made the script work how I wanted it to work. Thank you again! – GMBeniamin Mar 30 '18 at 14:38
1

Here's a solution for a similar requirement described in the post.

In my case, I have a set of preferred directories that I navigate to regularly. I keep this list of directories in a file called ~/dirs.txt

In ~/.bashrc I have set up 2 aliases to support accessing the directory list:

  1. add parent directory: apd

Add the current path I'm at, into the ~/dirs.txt file

~~~

  1. change current directory: ccd

List each line as a menu option, and from the choice selected - then navigate to the directory for that menu item

alias apdnwln="echo '  '  >> ~/dirs.txt"
alias apd=" pwd >> ~/dirs.txt; apdnwln"
alias ccd="showCcdMenu"

showCcdMenu(){

  echo "----------------"
  echo "    Go To path: "
  echo "----------------"
  echo ""

  dirsFile='/Users/someusername/dirs.txt'
  IFS=$'\n'       # make newlines the only separator
  set -f          # disable globbing

  count=0
  for i in $(cat < "$dirsFile"); do
    count=$((count+1))

    if [[ ( "$count"  -lt "10" ) ]] ; then

      printf " "
    fi

    echo " $count : $i"
  done

  printf "\n"
  echo "Enter your choice"
  read itemChoice
  echo "your choice: $itemChoice"
  #echo $answer

  count=0
  for i in $(cat < "$dirsFile"); do
    count=$((count+1))

    if [[ ( "$count"  -eq "$itemChoice" ) ]] ; then

      echo " going to dir: $i"
      cd $i
      break
    fi
  done
}

The following SO (& Co.) posts made this solt. possible .. thanks SO!

Gene Bo
  • 8,869
  • 6
  • 70
  • 118
1

this project creates a excellent menu for cd history.

https://github.com/xhawk18/fast_cd_menu

To install it, try ---

curl -o- https://raw.githubusercontent.com/xhawk18/fast_cd_menu/master/install.sh | bash
xhawk18
  • 111
  • 4