不知道你有沒有和我一樣的需求,平常會負責幾個項目的開發,又習慣使用git指令行管理開發代碼。每次要送出代碼,都要找到項目的目錄,然後打開一個指令行視窗,或者頻繁切換目錄到想要的目錄,到最後,你的工作列可能有N個git指令行視窗,雖然操作也沒那麼麻煩,但是做重複的事總是很不舒服。
是以簡單的寫了個bash腳本,友善切換目錄,雖然簡單,但是用着還覺得挺友善的,有興趣的可以看下,https://github.com/eussi/SimpleScripts/tree/master/gitTools。
我用的電腦是windows系統,在我電腦上開發環境是這樣的,自己有個工作目錄,負責的項目都放在這個目錄下面,每個項目有他自己的辨別。假設這個目錄是APP,下面A,B,C等項目,目錄層級可能如下:
./APP
./APP/aaaa
./APP/aaaa/aaaa
./APP/aaaa/aaaa/app.properties
./APP/bbbbb
./APP/bbbbb/app.properties
./APP/cccccccc
./APP/cccccccc/app.properties
./APP/dddd
辨別每個項目資訊的檔案是app.properties,檔案裡内容可能包含appid等應用的資料,檔案内容可能是這樣:
appid=100012345
bb=e
cc=3
當然檔案app.properties可能不存在,檔案中的appid也可能不存在。
#1
剛剛開始想法是這樣的,需要有一個指令,這個指令不能很長,傳入工作目錄,這個指令會将所有項目以清單的形式展示出來,然後自己輸入想進入哪個項目目錄,就可以立刻進入,并且這個指令可以在電腦的任何一個目錄下執行。
這樣我随時打開git,随時切換目錄,即使在一個項目的目錄中,也可以切換到另外一個項目的目錄下。
‘很短的指令’可以通過alias别名來實作,邏輯可以通過bash腳本來實作,切換目前所在目錄,可以通過
source或.
執行bash腳本來實作。
于是有了下面一個版本的腳本
list_v1.sh
:
#!/bin/bash
#program:
# Switch application directory
#author:
# xuemingwang 2020-11-21
#usage:
# source list_v1.sh dir
#print format
WHITE="\033[37m"
RED="\033[31m"
BOLD="\033[1m"
#print func
printMsg() {
mesg=$1
head=$2
tail=$3
echo -e "${head}${mesg}${tail}"
}
ROOT_DIR=$1
APP_FILENAME=app.properties
APPID_SYMPOL=appid
NULL_APPID=#########
#main
main() {
echo ""
echo "******************************"
printMsg "APP_DIR:"$ROOT_DIR $WHITE $BOLD
echo "******************************"
#get list
echo -e "\nLIST:"
index=0
for var in `ls $ROOT_DIR`
do
subDir=$ROOT_DIR"/"$var
if [ ! -d $subDir ]; then
continue
fi
#find appid
appfilePath=`find $subDir -name $APP_FILENAME`
if [ -n "$appfilePath" ]; then
app_arr[index]="["$index"]. "`sed -n '/^'"$APPID_SYMPOL"'=\([0-9]*\)/s//\1/p' $appfilePath`" "$var
else
app_arr[index]="["$index"]. "$NULL_APPID" "$var
fi
#echo "${app_arr[index]}"
index=$((index+1))
done
#print list
for ((k=0; k<$index; k++))
do
printMsg "${app_arr[$k]}" $WHITE $BOLD
done
#choose where to to
echo "******************************"
echo -e "\nOPTIONS:"
while true
do
echo Please choose where to go or exit by Q:
read input
#echo $input
if [ "Q" = "$input" -o "q" = "$input" ]; then
echo "exit"
#exit 0
break
fi
find=0
for ((k=0; k<$index; k++))
do
echo "${app_arr[$k]}" | grep "$input" > /dev/null 2>&1
if [ $? -eq 0 ]; then
#find
find=1
retDir=`echo ${app_arr[$k]} | awk '{print $3}'`
cd $ROOT_DIR"/"$retDir
break
fi
done
#for remove exit
if [ "$find" = "1" ]; then
break
fi
echo -e "Please enter the string contained in the list.\n"
done
}
if [ ! $# -eq 1 ]; then
echo Usage: with one parameters, the root of application directory.
#exit -1 #Exit cannot be used in order to switch execution directories
else
if [ ! -d $ROOT_DIR ]; then
echo $ROOT_DIR "is not exist."
#exit -1 #Exit cannot be used in order to switch execution directories
else
if [ ! -d $ROOT_DIR ]; then
echo $ROOT_DIR "is not exist."
else
main
fi
fi
fi
大緻邏輯是周遊工作目錄,并通過find指令查找辨別檔案app.properties,再在檔案中提取出appid對應的值,通過清單的形式展示出來。
此時将腳本加入path路徑中,我是在home目錄裡建立了bin目錄,即C:\Users\wangx\bin,腳本放在該目錄下,然後打開bash指令行通過alias設定指令别名,如下:
$ alias cmds='. list_v1.sh /C/Users/wangx/Desktop/APP'
上面指令用
cmds
(cmd switch)代替
. list_v1.sh /C/Users/wangx/Desktop/APP
指令,注意運作該指令的時候我使用的
.
或者
source
, 因為要切換目前執行的目錄,使用
sh
隻能切換子shell的目錄,對目前目錄切換無效。
這個時候便可以友善切換目錄了,操作如下:
$ cmds
******************************
APP_DIR:/C/Users/wangx/Desktop/APP
******************************
LIST:
[0]. 100012345 aaaa/
[1]. 100016789 bbbbb/
[2]. 200016789 cccccccc/
[3]. ######### dddd/
******************************
OPTIONS:
Please choose where to go or exit by Q:
16789
$ pwd
/C/Users/wangx/Desktop/APP/bbbbb
$ cmds
******************************
APP_DIR:/C/Users/wangx/Desktop/APP
******************************
LIST:
[0]. 100012345 aaaa/
[1]. 100016789 bbbbb/
[2]. 200016789 cccccccc/
[3]. ######### dddd/
******************************
OPTIONS:
Please choose where to go or exit by Q:
ddd
$ pwd
/C/Users/wangx/Desktop/APP/dddd
$ cmds
******************************
APP_DIR:/C/Users/wangx/Desktop/APP
******************************
LIST:
[0]. 100012345 aaaa/
[1]. 100016789 bbbbb/
[2]. 200016789 cccccccc/
[3]. ######### dddd/
******************************
OPTIONS:
Please choose where to go or exit by Q:
q
exit
這樣看起來已經完全滿足需求了,于是拿到自己電腦上開始使用了,一用就尴尬了,工作目錄下一二十個應用,每次要切換目錄時,輸入指令,展示出來實在是太慢了,還不如我之前直接手動切換。
#2
一方面git的bash指令行執行linux上的一些指令速度确實慢很多,另一方面懷疑自己使用find指令查找appid效率可能太低了,畢竟一個項目中檔案可能很多,查找檔案數量多起來将會耗時很高,兩方面一起算下來,腳本執行速度慢也是理所當然的吧。于是想着先優化下find指令吧。
一般在一個公司,所有的項目的appid存放的位置一般是一樣的,比如都在應用根目錄下有個app.properties,或者在第二層目錄下,是以就沒必要通過find搜尋一遍了,采用直接讀取這兩個位置的app.properties,拿到appid,拿不到就結束。即:
getAppId() {
rootDir=$1
filePath=$ROOT_DIR'/'$rootDir'/'$APP_FILENAME
#src\main\resources\META-INF\app.properties
if [ -f "$filePath" ]; then
echo `sed -n '/^'"$APPID_SYMPOL"'=\([0-9]*\)/s//\1/p' $filePath`
else
find=0
for var in `ls $ROOT_DIR'/'$rootDir`
do
secondFilePath=$ROOT_DIR'/'$rootDir'/'$var'/'$APP_FILENAME
#echo $secondFilePath
if [ -f "$secondFilePath" ]; then
echo `sed -n '/^'"$APPID_SYMPOL"'[ ]*=[ ]*\([0-9]*\)/s//\1/p' $secondFilePath`
find=1
break #At most two layer
fi
done
if [ $find = "0" ]; then
echo $NULL_APPID
fi
fi
}
于是有了第二版腳本
list_v2.sh
:
#!/bin/bash
#program:
# Switch application directory
#author:
# xuemingwang 2020-11-21
#usage:
# source list.sh dir
#print format
WHITE="\033[37m"
RED="\033[31m"
BOLD="\033[1m"
#print func
printMsg() {
mesg=$1
head=$2
tail=$3
echo -e "${head}${mesg}${tail}"
}
ROOT_DIR=$1
APP_FILENAME=app.properties
APPID_SYMPOL=appid
NULL_APPID=#########
getAppId() {
rootDir=$1
filePath=$ROOT_DIR'/'$rootDir'/'$APP_FILENAME
#src\main\resources\META-INF\app.properties
if [ -f "$filePath" ]; then
echo `sed -n '/^'"$APPID_SYMPOL"'=\([0-9]*\)/s//\1/p' $filePath`
else
find=0
for var in `ls $ROOT_DIR'/'$rootDir`
do
secondFilePath=$ROOT_DIR'/'$rootDir'/'$var'/'$APP_FILENAME
#echo $secondFilePath
if [ -f "$secondFilePath" ]; then
echo `sed -n '/^'"$APPID_SYMPOL"'[ ]*=[ ]*\([0-9]*\)/s//\1/p' $secondFilePath`
find=1
break #At most two layer
fi
done
if [ $find = "0" ]; then
echo $NULL_APPID
fi
fi
}
#main
main() {
echo ""
echo "******************************"
printMsg "APP_DIR:$ROOT_DIR" $WHITE $BOLD
echo "******************************"
#get list
echo -e "\nLIST:"
index=0
for var in `ls $ROOT_DIR`
do
subDir=$ROOT_DIR"/"$var
if [ ! -d $subDir ]; then
continue
fi
#find appid
#appfilePath=`find $subDir \( -path "./.git" -o -path ".git" -o -path "./.idea" \) -prune -o -name $APP_FILENAME`
appId=`getAppId $var`
#if [ -n "$appfilePath" ]; then
# app_arr[index]="["$index"]. "`sed -n '/^'"$APPID_SYMPOL"'=\([0-9]*\)/s//\1/p' $appfilePath`" "$var
#else
# app_arr[index]="["$index"]. "$NULL_APPID" "$var
#fi
app_arr[index]=`printf "[%02s]. %-9s %s" "$index" "$appId" "$var"`
printMsg "${app_arr[index]}" $WHITE $BOLD
#echo "${app_arr[index]}"
index=$((index+1))
done
#print list
#for ((k=0; k<$index; k++))
#do
# printMsg "${app_arr[$k]}" $WHITE $BOLD
#done
#choose where to to
echo "******************************"
echo -e "\nOPTIONS:"
while true
do
echo Please choose where to go or exit by Q:
read input
#echo $input
if [ "Q" = "$input" -o "q" = "$input" ]; then
echo "exit"
#exit 0
break
fi
find=0
for ((k=0; k<$index; k++))
do
echo "${app_arr[$k]}" | grep "$input" > /dev/null 2>&1
if [ $? -eq 0 ]; then
#find
find=1
retDir=`echo ${app_arr[$k]} | awk '{print $3}'`
cd $ROOT_DIR"/"$retDir
echo -e "\nCURRENT: "$ROOT_DIR"/"$retDir
break
fi
done
#for remove exit
if [ "$find" = "1" ]; then
break
fi
echo -e "Please enter the string contained in the list.\n"
done
}
if [ ! $# -eq 1 ]; then
echo Usage: with one parameters, the root of application directory.
#exit -1 #Exit cannot be used in order to switch execution directories
else
if [ ! -d $ROOT_DIR ]; then
echo $ROOT_DIR "is not exist."
#exit -1 #Exit cannot be used in order to switch execution directories
else
if [ ! -d $ROOT_DIR ]; then
echo $ROOT_DIR "is not exist."
else
main
fi
fi
fi
同樣将腳本設定放到path目錄下,然後設定别名
$ alias cmds='. list_v2.sh /C/Users/wangx/Desktop/APP'
運作效果如下:
$ cmds
******************************
APP_DIR:/C/Users/wangx/Desktop/APP
******************************
LIST:
[00]. 100012345 aaaa/
[01]. 100016789 bbbbb/
[02]. 200016789 cccccccc/
[03]. ######### dddd/
******************************
OPTIONS:
Please choose where to go or exit by Q:
bbb
CURRENT: /C/Users/wangx/Desktop/APP/bbbbb/
$ pwd
/C/Users/wangx/Desktop/APP/bbbbb
$ cmds
******************************
APP_DIR:/C/Users/wangx/Desktop/APP
******************************
LIST:
[00]. 100012345 aaaa/
[01]. 100016789 bbbbb/
[02]. 200016789 cccccccc/
[03]. ######### dddd/
******************************
OPTIONS:
Please choose where to go or exit by Q:
q
exit
$ pwd
/C/Users/wangx/Desktop/APP/bbbbb
運作沒問題,拿到自己電腦上測試,同樣的問題,還是運作的太慢,看來指令不是主要的影響因素,之後也嘗試網上查找優化git執行指令的速度,但是效果都不大。上面的方案看來并不能解決問題。
#3
因為git執行腳本始終速度都很慢,隻能通過其他方法來實作自己的需求了。
再細想想,由于自己負責開發的項目數量和名稱變動并不是很大,我可以将資訊先緩存起來,等到資料變動時,我再進行更新,并且我也沒必要每次列出來之後選擇要進入的目錄,我還想要一個立刻進入某目錄的功能,切換速度更快更友善。
于是想了另外一個方案,修改腳本,傳入不同的參數,實作三個功能:
- 将項目資料緩存到某個檔案中
- 讀取緩存檔案,展示資料,選擇進入目錄
- 讀取緩存檔案,直接進入目錄
這樣,直接讀取一個緩存檔案,然後選擇進入某個項目的目錄,不至于執行也是龜速吧。于是産生了下面的腳本
list_v3.sh
:
#!/bin/bash
#program:
# Switch application directory
#author:
# xuemingwang 2020-11-21
#usage:
# source list_v3.sh dir -g
# source list_v3.sh dir -l
# source list_v3.sh dir -s str
#print format
WHITE="\033[37m"
RED="\033[31m"
BOLD="\033[1m"
#params
[email protected]
INPUT_PARAMS_NUM=$#
#variable
TEMP_FILE=/.list_v3
ROOT_DIR=$1
FLAG=$2
FLAG_VALUE=$3
APP_FILENAME=app.properties
APPID_SYMPOL=appid
NULL_APPID=#########
#print func
printMsg() {
mesg=$1
head=$2
tail=$3
echo -e "${head}${mesg}${tail}"
}
getAppId() {
rootDir=$1
filePath=$ROOT_DIR'/'$rootDir'/'$APP_FILENAME
#src\main\resources\META-INF\app.properties
if [ -f "$filePath" ]; then
echo `sed -n '/^'"$APPID_SYMPOL"'=\([0-9]*\)/s//\1/p' $filePath`
else
find=0
for var in `ls $ROOT_DIR'/'$rootDir`
do
secondFilePath=$ROOT_DIR'/'$rootDir'/'$var'/'$APP_FILENAME
#echo $secondFilePath
if [ -f "$secondFilePath" ]; then
echo `sed -n '/^'"$APPID_SYMPOL"'[ ]*=[ ]*\([0-9]*\)/s//\1/p' $secondFilePath`
find=1
break #At most two layer
fi
done
if [ $find = "0" ]; then
echo $NULL_APPID
fi
fi
}
#Generate temporary cache
generate() {
tempFile=$TEMP$TEMP_FILE
> $tempFile
index=0
for var in `ls $ROOT_DIR`
do
subDir=$ROOT_DIR"/"$var
if [ ! -d $subDir ]; then
continue
fi
appId=`getAppId $var`
printf "%-9s %s\n" "$appId" "$var" >> $tempFile
index=$((index+1))
done
}
#List the options
list() {
tempFile=$TEMP$TEMP_FILE
if [ ! -f $tempFile ]; then
echo "err: need a temporary document."
else
echo -e "\nLIST:"
index=0
while read line
do
app_arr[index]=`printf "%02s %s" "$index" "$line"`
echo ${app_arr[index]}
index=$((index+1))
done < $tempFile
echo -e "\nOPTIONS:"
while true
do
echo Please choose where to go or exit by Q:
read input
#echo $input
if [ "Q" = "$input" -o "q" = "$input" ]; then
echo "exit"
#exit 0
break
fi
find=0
for ((k=0; k<$index; k++))
do
echo "${app_arr[$k]}" | grep "$input" > /dev/null 2>&1
if [ $? -eq 0 ]; then
#find
find=1
retDir=`echo ${app_arr[$k]} | awk '{print $3}'`
cd $ROOT_DIR"/"$retDir
echo -e "\nCURRENT: "$ROOT_DIR"/"$retDir
break
fi
done
#for remove exit
if [ "$find" = "1" ]; then
break
fi
echo -e "Please enter the string contained in the list.\n"
done
fi
}
#Switch directory
switch(){
tempFile=$TEMP$TEMP_FILE
if [ ! -f $tempFile ]; then
echo "err: need a temporary document."
else
find=0
while read line
do
echo "$line" | grep "$FLAG_VALUE" > /dev/null 2>&1
if [ $? -eq 0 ]; then
#find
find=1
retDir=`echo ${line} | awk '{print $2}'`
cd $ROOT_DIR"/"$retDir
echo -e "\nCURRENT: "$ROOT_DIR"/"$retDir
break
fi
done < $tempFile
if [ "$find" != "1" ]; then
echo -e "No such app dir.\n"
fi
fi
}
#main
main() {
if [[ $FLAG != -* ]]; then
FLAG_VALUE=$FLAG
FLAG="-s" #default value -s
fi
case $FLAG in
"-l")
list
;;
"-g")
generate
;;
"-s")
switch
;;
*)
echo "Unsupported commands."
;;
esac
}
#basic check
if [ $# -gt 3 ]; then
echo Usage: Up to three parameters, root_dir, flag and the value.
#exit -1 #Exit cannot be used in order to switch execution directories
else
if [ ! -d $ROOT_DIR ]; then
echo $ROOT_DIR "is not exist."
#exit -1 #Exit cannot be used in order to switch execution directories
else
if [ ! -d $ROOT_DIR ]; then
echo $ROOT_DIR "is not exist."
else
main
fi
fi
fi
同樣将腳本設定放到path目錄下,然後設定三個功能的别名
$ alias cmdg='sh list_v3.sh /C/Users/wangx/Desktop/APP -g'
$ alias cmdl='. list_v3.sh /C/Users/wangx/Desktop/APP -l'
$ alias cmds='. list_v3.sh /C/Users/wangx/Desktop/APP -s'
執行效果如下:
$ cmdg
$ cmdl
LIST:
00 100012345 aaaa/
01 100016789 bbbbb/
02 200016789 cccccccc/
03 ######### dddd/
OPTIONS:
Please choose where to go or exit by Q:
bb
CURRENT: /C/Users/wangx/Desktop/APP/bbbbb/
$ cmds aaa
CURRENT: /C/Users/wangx/Desktop/APP/aaaa/
$ cmds 2000
CURRENT: /C/Users/wangx/Desktop/APP/cccccccc/
$ pwd
/C/Users/wangx/Desktop/APP/cccccccc
其中cmdg生成檔案内容如下:
$ cat $TEMP/.list_v3
100012345 aaaa/
100016789 bbbbb/
200016789 cccccccc/
######### dddd/
如果你往工作目錄裡添加了新的項目,運作一下
cmdg
更新下這個檔案,然後又可以使用
cmdl
和
cmds
切換目錄了,速度完全能達到需求。
終于算是搞定了。
使用了大概一個月了,确實用着比之前舒服多了。
另外,如果你有多個工作目錄,這個腳本也可以使用,你可以将别名設定成不同的名字,來操作不同目錄。不過需要注意的是,存放生成的檔案要調整,否則會互相覆寫,可以将傳入工作目錄的字元串進行hash,然後拼接到生成檔案名的後面來做區分。不過目前我這裡這樣就夠了,就不多搞了。