歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> 關於Unix >> bash遍歷目錄

bash遍歷目錄

日期:2017/3/6 14:25:45   编辑:關於Unix
腳本的最初原型是當年用fvwm的時候為了山寨一個生成家目錄下的樹形結構菜單寫的一個廣度優先遍歷;後來在把文件系統從ext3轉到ext4的時候重新分區,把文件備份到windows上,

  腳本的最初原型是當年用fvwm的時候為了山寨一個生成家目錄下的樹形結構菜單寫的一個廣度優先遍歷;後來在把文件系統從ext3轉到ext4的時候重新分區,把文件備份到windows上,結果還原回來的時候權限都亂了,於是把queue整理了一下寫成一個單獨的腳本用來改權限;後來還實現了一個深度優先遍歷的版本。今天把這兩個函數都整理一下。一般來說簡單的操作用find+各種工具就行了,除非是對遍歷順序有要求或操作比較復雜。

  #!/bin/bash

  # http://ouonline.net/

  IFS=$(echo -en "\n\b") # in case of space(s) in dentry name

  # -------------------------------------------------------------------------- #

  function dfs()

  {

  #if [ $# -ne 2 ]; then

  #echo "function call error: dfs callback root_dir" >&2

  #exit -1

  #fi

  callback=$1

  root=$2

  let top=1

  stack[0]="$root" # root dir

  while [ $top -gt 0 ]; do

  let top=$top-1

  parent="${stack[$top]}"

  for i in `ls "$parent"`; do

  fpath="$parent/$i"

  $callback "$fpath" # do whatever you want

  if [ -d "$fpath" ]; then

  stack[$top]="$fpath"

  let top=$top+1

  fi

  done

  done

  }

  function bfs()

  {

  #if [ $# -ne 2 ]; then

  #echo "function call error: bfs callback root_dir" >&2

  #exit -1

  #fi

  callback=$1

  root=$2

  let begin=0

  let end=1

  queue[0]="$root" # root dir

  while [ $begin -lt $end ]; do

  for i in `ls "${queue[$begin]}"`; do

  fpath="${queue[$begin]}/$i"

  $callback "$fpath" # do whatever you want

  if [ -d "$fpath" ]; then

  queue[$end]="$fpath"

  let end=$end+1

  fi

  done

  unset queue[$begin]

  let begin=$begin+1

  done

  }

  這裡之所以用了`ls dir`而不是用”dir/*”這樣的格式是因為當dir為空的時候直接給的字符串”dir/*”而不是不進入循環,這樣在循環內還得先判斷一下dentry是否存在。

  這兩個函數可以用來做一些復雜一點的遍歷工作,例如用來統計代碼行數:

  let sum=0

  function count_line()

  {

  if ! [ -d "$1" ]; then

  fname=`basename "$1"`

  ftype=`echo "$fname" | awk -F. '{print $NF}'`

  if [[ $ftype == "c" || $ftype == "cpp" || $ftype == "h" || "$fname" == "Makefile" ]]; then

  let n=`wc -l "$1" | awk '{print $1}'`

  echo -e "$n\t\t$1"

  let sum=$sum+$n

  fi

  fi

  }

  dfs count_line /path/to/project

  echo "----------------------------------------------------"

  echo -e "$sum\t\ttotal"

  還有當時用來生成fvwm菜單的腳本,不過現在已經折騰不動了。

  #!/bin/bash

  editor="leafpad"

  browser="opera"

  pdfviewer="kpdf"

  picviewer="gpicview"

  docviewer="ooffice -writer"

  pptviewer=""

  videoplayer="gmplayer"

  audioplayer="audacious2"

  tarviewer=""

  # 生成的該目錄菜單名稱是MainDirMenu

  function makemenu()

  {

  # makemenu接受四個參數:第一個是目錄(注意是絕對路徑),第二個是該目錄在隊列中的位置,

  # 第三個是該目錄下第一個子目錄在隊列中的位置,第四個是要建立目錄列表的根目錄名稱。

  counter=0

  echo "DestroyMenu $4$2Menu"

  echo "AddToMenu $4$2Menu"

  for i in "$1"/*;do

  fname=`basename "$i"`

  if [ -d "$i" ];then

  echo "+ \"$fname%folder-32.png%\" PopUp `expr $3 + $counter`Menu Item 100 0"

  let counter=$counter+1

  else

  case "`echo $fname | awk -F "." '{print $NF}'`" in # 判斷類型

  "pdf")

  echo "+ \"$fname%pdf-32.png%\" Exec exec $pdfviewer \"$i\"";;

  "doc" | "docx" | "odt" | "rtf" | "xml")

  echo "+ \"$fname%document-32.png%\" Exec exec $docviewer \"$i\"";;

  "ppt")

echo + \$fname%presentation-32.png%\ Exec exec $pptviewer \$i\;; jpg | png) echo + \$fname%image-32.png%\ Exec exec $picviewer \$i\;; avi | mkv | rm | rmvb | wmv) echo + \$fname%video-32.png%\ Exec ex

  echo "+ \"$fname%presentation-32.png%\" Exec exec $pptviewer \"$i\"";;

  "jpg" | "png")

  echo "+ \"$fname%image-32.png%\" Exec exec $picviewer \"$i\"";;

  "avi" | "mkv" | "rm" | "rmvb" | "wmv")

  echo "+ \"$fname%video-32.png%\" Exec exec $videoplayer \"$i\"";;

  "mp3" | "wma")

  echo "+ \"$fname%audio-32.png%\" Exec exec $audioplayer \"$i\"";;

  "gz" | "bz2" | "tar" | "zip" | "rar" | "deb" | "rpm")

  echo "+ \"$fname%tarball-32.png%\" Exec exec $tarviewer \"$i\"";;

  "iso")

  echo "+ \"$fname%iso-32.png%\" Exec exec $tarviewer \"$i\"";;

  "htm" | "html" | "mht" | "xml")

  echo "+ \"$fname%html-32.png%\" Exec exec $browser \"$i\"";;

  "exe" | "msi")

  echo "+ \"$fname%bin-32.png%\"";;

  "ttf")

  echo "+ \"$fname%font-32.png%\"";;

  *)

  if [ -f "$i" ] && [ -x "$i" ];then

  echo "+ \"$fname%script-32.png%\" Exec exec $editor \"$i\""

  else # 不能識別類型的一律用記事本打開

  echo "+ \"$fname%text-32.png%\" Exec exec $editor \"$i\""

  fi

  ;;

  esac

  fi

  done

  }

  if [ $# -eq 1 ];then

  makemenu "$1" "" 1 "MainDir" # 生成主目錄菜單,第四個參數僅在此處使用

  elif [ $# -eq 2 ] && [ "$1" = "-r" ];then

  makemenu "$2" "" 1 "MainDir"

  x=1

  p=0

  queue[0]="$2" # 要生成菜單的主目錄入隊

  while [ $p -lt $x ];do

  for i in "${queue[$p]}"/*;do

  if [ -d "$i" ];then

  queue[$x]="$i"

  let x=$x+1

  fi

  done

  let p=$p+1

  #if [ $p -lt $x ];then

  makemenu "${queue[$p]}" $p $x "" # x是該目錄下第一個子目錄的位置,注意第四個參數為空

  #fi

  done

  else

  echo "Usage: `basename $0` [ -r ] absolute path(without trailing slash)"

  fi

Copyright © Linux教程網 All Rights Reserved