简体   繁体   中英

How to print in columns with tcsh script

I am forced to work with tcsh shell and I wanted to make myself a little more comfortable traversing around in commonly visited directories. So I looked for 'bookmarking' tool but I could not find one, so I went ahead and wrote a small tcsh scipt. My only complaint to how it works is that I can only print into single column in terminal. This is was not an issue with the first draft of the script as I wrote it in bash, but realized I cannot change directory from child process on running different shell...

This approached worked for bash, but it does not for tcsh:

for key in "${!map[@]}"; do
    if [[ ${key} =~ $2 ]]; then
      printf "%-8s\n" "${key}"
    fi
  done | sort | column

I could also force similar behavior through command line but it's suboptimal:

bookmark.sh -l | sort | column

Here is my full "Frankenstein" code:

#!/bin/tcsh
set BM = "${HOME}/.gtk-bookmarks"
set root = "file://"
set keys = ()
set values = ()

# Check if bookmarks file exists. If so parse it into hash
if ( -r $BM ) then
  foreach line ( "`cat $BM |grep -v KEY`" )
    set key = `echo $line | cut -d " " -f 2`
    set value = `echo $line | cut -d " " -f 1 | sed 's/file:\/\///g'` 
    set keys = ( $keys "$key" )
    set values = ( $values "$value" )
  end
else
 echo "[ERROR]: Bookmark file $BM does not exists."
 exit 1
endif

if ( $# == 0 ) then
  #############################
  ## D E F A U L T   L I S T ##
  #############################
  set found = 0
  foreach key ($keys)
    set found = 1
    printf "%-8s\n" "$key"
  end
  if ($found == 0) then
    echo "[ERROR]: No bookmarks found."
    exit 1
  else
    exit 0
  endif
else
  #############
  ## H E L P ##
  #############
  if ( "$argv[1]" == "-h" || "$argv[1]" == "--help" ) then
    echo "Purpose: Work with bookmarks within terminal window."
    echo "-a|--add                Add a bookmark <name> <path>."
    echo "-e|--edit               Edit existing bookmark <name> <new_path>."
    echo "-f|--find               Find bookmark <string>,"
    echo "-l|--list               List available bookmarks."
    echo "-v|--view               View particular bookmark <name>."
    echo "-cd|--change_directory  Change directory to given bookmark <name>."
    echo "-h|--help               Prints help."  
  ###########
  ## A D D ##
  ###########
  else if ( "$argv[1]" == "-a" || "$argv[1]" == "--add" ) then
    echo "Adding:"

    if ($# != 3 ) then
      echo "[ERROR]: bm -a|--add <bookmarkName> <validPath>."
      exit 1
    endif

    set i = 1
    set found = 0
    while($i <= ${#keys})
      if ( "$keys[$i]" == "$argv[2]" ) then
        set found = 1
        break
      endif
      @ i++
    end

    if ( $found == 0 ) then
      if ( -d $argv[3] || -f $argv[3] ) then
        set value = `realpath -s $argv[3]`
        echo "$argv[2] $value"
        echo "file://$value $argv[2]" >> $BM
        exit 0
      else
        echo "[ERROR]: $argv[3] is neither a file or directory."
        exit 1
      endif
    else
      echo "[ERROR]: $argv[2] bookmark already exists."
      exit 1
    endif
  #############
  ## E D I T ##
  #############
  else if ( "$argv[1]" == "-e" || "$argv[1]" == "--edit" ) then
    echo "Editing:"
    
    if ($# != 3 ) then
      echo "[ERROR]: bm -e|--edit <bookmarkName> <validPath>."
      exit 1
    endif

    set i = 1
    set found = 0
    while($i <= ${#keys})
      if ( "$keys[$i]" == "$argv[2]" ) then
        set found = 1
        break
      endif
      @ i++
    end

    if ($found > 0) then
      if ( -d $values[$i] || -f $values[$i] ) then
        if ( -d $argv[3] || -f $argv[3] ) then
          set value = `realpath -s $argv[3]`
          # update file
          set k = 1
          while ($k <= ${#keys})
            if ( $k == $i ) then
              echo "[INFO]: Previous $keys[$k] : $values[$k]"
              set line = "file://$value $keys[$k]"
              echo "[INFO]: Updated $keys[$k] : $value"
            else
              set line = "file://$values[$k] $keys[$k]"
            endif

            if ( $k == 1 ) then
              echo $line > $BM
            else
              echo $line >> $BM
            endif
            @ k++
          end
          exit 0
        else
          echo "[ERROR]: $argv[3] is neither a file or directory."
          exit 1
        endif
      else
        echo "[ERROR]: $values[$i] is neither a file or directory."
        exit 1
      endif
    else
      echo "[ERROR]: $argv[2] bookmark does not exist."
      exit 1
    endif
  #############
  ## L I S T ##
  #############
  else if ("$argv[1]" == "-l" || "$argv[1]" == "--list") then
    echo "List:"

    if ($# > 1 ) then
      echo "[ERROR]: bm -l|--list|<nothing>."
      exit 1
    endif

    set found = 0
    foreach key ($keys)
      set found = 1
      printf "%-8s\n" "$key"
    end
    if ($found == 0) then
      echo "[ERROR]: No bookmarks found."
      exit 1
    else
      exit 0
    endif
  #############
  ## F I N D ##
  #############
  else if ( "$argv[1]" == "-f" || "$argv[1]" == "--find" ) then
    echo "Find:"

    if ($# != 2 ) then
      echo "[ERROR]: bm -f|--find <string>."
      exit 1
    endif

    set found = 0
    foreach key ($keys)
      if ( $key =~ *$argv[2]* ) then
        set found = 1
        printf "%-8s\n" "$key"
      endif
    end
    if ($found == 0) then
      echo "[ERROR]: No bookmarks containing $argv[2] found."
      exit 1
    else
      exit 0
    endif
  #########
  ## C D ##
  #########
  else if ( "$argv[1]" == "-cd" || "$argv[1]" == "--change_directory" ) then
    echo "Changing directory & listing:"

    if ($# != 2 ) then
      echo "[ERROR]: bm -cd|--change_directory <bookmarkName>."
      exit 1
    endif

    set i = 1
    while($i <= ${#keys})
      if ( "$keys[$i]" == "$argv[2]" ) then
        cd "$values[$i]"
        ls ./
        exit 0
      endif
      @ i++
    end
    echo "[ERROR]: $argv[2] bookmark does not exists."
    exit 1
  #############
  ## V I E W ##
  #############
  else if ( "$argv[1]" == "-v" || "$argv[1]" == "--view" ) then
    echo "View:"

    if ($# != 2 ) then
      echo "[ERROR]: bm -v|--view <bookmarkName>."
      exit 1
    endif

    set i = 1
    while($i <= ${#keys})
      if ( "$keys[$i]" == "$argv[2]" ) then
        echo "$keys[$i] : $values[$i]"
        exit 0
      endif
      @ i++
    end
    echo "[ERROR]: $argv[2] bookmark does not exists."
    exit 1
  #####################
  ## Q U I C K   C D ##
  #####################
  else
    set i = 1
    while($i <= ${#keys})
      if ( "$keys[$i]" == "$argv[1]" ) then
        echo "Changing directory & listing:"
        cd "$values[$i]"
        ls ./
        exit 0
      endif
      @ i++
    end
    echo "[ERROR]: Unknown command option or bookmark $argv[1]. Use -h or --help to available command options."   
    exit 1
  endif
endif

PS: I know my code is nowhere near efficient or pretty, but it does the job. I just want to utilize the entire available terminal width.

EDIT #1 : I forgot to mention that in order to make my script effective in changing the directory when called, I have an alias that source it:

alias bm 'source /home/bookmark.sh'

It looks a like job for $CDPATH check out here .

Long story short -- that is $PATH for directories; autocompletes cd ... by making a lookup in subdirs under paths.

Works something like:

$ set cdpath = ($cdpath /path/to/dir1/ /path/to/dir2/ /path/to/dir3/)
$ ls /path/to/dir1/
ddir1
cd ddir1 # will jump into /path/to/dir1/ddir1
cd d<TAB> # SHOULD autocomplete, 
          # will update when proper settings is found

Maybe you also will benefit by setting some fancy inputrc settings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM