2
linux常用脚本之z.sh与v.sh
source link: https://chegva.com/2615.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
linux常用脚本之z.sh与v.sh | CHEGVA
z.sh用于linux常用目录跳转,v.sh用于常用vim编辑文件
将z.sh放到~目录下,在.bashrc或.zshrc里添加[[ -f ~/z.sh ]] && source ~/z.sh
cp v.sh /usr/local/bin/v && chmod +x /usr/local/bin/v
z.sh用于多个常用目录之间的跳转,相比cd好用很多。在命令行上敲z回车,便会出现该目录的完整目录名,下次再进入的话,只需敲z u(这时按下tab键会帮你补齐的,若是有两个同名的会连续变化)
z.sh使用方法:https://github.com/rupa/z/blob/master/README
# Copyright (c) 2009 rupa deadwyler. Licensed under the WTFPL license, Version 2
# maintains a jump-list of the directories you actually use
#
# INSTALL:
# * put something like this in your .bashrc/.zshrc:
# . /path/to/z.sh
# * cd around for a while to build up the db
# * PROFIT!!
# * optionally:
# set $_Z_CMD in .bashrc/.zshrc to change the command (default z).
# set $_Z_DATA in .bashrc/.zshrc to change the datafile (default ~/.z).
# set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
# set $_Z_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself.
# set $_Z_EXCLUDE_DIRS to an array of directories to exclude.
# set $_Z_OWNER to your username if you want use z while sudo with $HOME kept
#
# USE:
# * z foo # cd to most frecent dir matching foo
# * z foo bar # cd to most frecent dir matching foo and bar
# * z -r foo # cd to highest ranked dir matching foo
# * z -t foo # cd to most recently accessed dir matching foo
# * z -l foo # list matches instead of cd
# * z -c foo # restrict matches to subdirs of $PWD
[ -d
"${_Z_DATA:-$HOME/.z}"
] && {
echo
"ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory."
}
_z() {
local
datafile=
"${_Z_DATA:-$HOME/.z}"
# if symlink, dereference
[ -h
"$datafile"
] && datafile=$(readlink
"$datafile"
)
# bail if we don't own ~/.z and $_Z_OWNER not set
[ -z
"$_Z_OWNER"
-a -f
"$datafile"
-a ! -O
"$datafile"
] &&
return
_z_dirs () {
while
read
line;
do
# only count directories
[ -d
"${line%%\|*}"
] &&
echo
$line
done
<
"$datafile"
return
0
}
# add entries
if
[
"$1"
=
"--add"
];
then
shift
# $HOME isn't worth matching
[
"$*"
=
"$HOME"
] &&
return
# don't track excluded directory trees
local
exclude
for
exclude
in
"${_Z_EXCLUDE_DIRS[@]}"
;
do
case
"$*"
in
"$exclude*"
)
return
;;
esac
done
# maintain the data file
local
tempfile=
"$datafile.$RANDOM"
awk
< <(_z_dirs 2>
/dev/null
) -
v
path=
"$*"
-
v
now=
"$(date +%s)"
-F
"|"
'
BEGIN {
rank[path] = 1
time
[path] = now
}
$2 >= 1 {
# drop ranks below 1
if
( $1 == path ) {
rank[$1] = $2 + 1
time
[$1] = now
}
else
{
rank[$1] = $2
time
[$1] = $3
}
count += $2
}
END {
if
( count > 9000 ) {
# aging
for
( x
in
rank ) print x
"|"
0.99*rank[x]
"|"
time
[x]
}
else
for
( x
in
rank ) print x
"|"
rank[x]
"|"
time
[x]
}
' 2>
/dev/null
>|
"$tempfile"
# do our best to avoid clobbering the datafile in a race condition.
if
[ $? -
ne
0 -a -f
"$datafile"
];
then
env
rm
-f
"$tempfile"
else
[
"$_Z_OWNER"
] &&
chown
$_Z_OWNER:$(
id
-ng $_Z_OWNER)
"$tempfile"
env
mv
-f
"$tempfile"
"$datafile"
||
env
rm
-f
"$tempfile"
fi
# tab completion
elif
[
"$1"
=
"--complete"
-a -s
"$datafile"
];
then
while
read
line;
do
[ -d
"${line%%\|*}"
] &&
echo
$line
done
<
"$datafile"
|
awk
-
v
q=
"$2"
-F
"|"
'
BEGIN {
if
( q == tolower(q) ) imatch = 1
q = substr(q, 3)
gsub(
" "
,
".*"
, q)
}
{
if
( imatch ) {
if
( tolower($1) ~ tolower(q) ) print $1
}
else
if
( $1 ~ q ) print $1
}
' 2>
/dev/null
else
# list/go
while
[
"$1"
];
do
case
"$1"
in
--)
while
[
"$1"
];
do
shift
;
local
fnd=
"$fnd${fnd:+ }$1"
;
done
;;
-*)
local
opt=${1:1};
while
[
"$opt"
];
do
case
${opt:0:1}
in
c)
local
fnd=
"^$PWD $fnd"
;;
e)
local
echo
=
echo
;;
h)
echo
"${_Z_CMD:-z} [-cehlrtx] args"
>&2;
return
;;
l)
local
list=1;;
r)
local
typ=
"rank"
;;
t)
local
typ=
"recent"
;;
x)
sed
-i -e
"\:^${PWD}|.*:d"
"$datafile"
;;
esac
; opt=${opt:1};
done
;;
*)
local
fnd=
"$fnd${fnd:+ }$1"
;;
esac
;
local
last=$1; [
"$#"
-gt 0 ] &&
shift
;
done
[
"$fnd"
-a
"$fnd"
!=
"^$PWD "
] ||
local
list=1
# if we hit enter on a completion just go there
case
"$last"
in
# completions will always start with /
/*) [ -z
"$list"
-a -d
"$last"
] &&
builtin
cd
"$last"
&&
return
;;
esac
# no file yet
[ -f
"$datafile"
] ||
return
local
cd
cd
=
"$( < <( _z_dirs ) awk -v t="
$(
date
+%s)
" -v list="
$list
" -v typ="
$typ
" -v q="
$fnd
" -F"
|" '
function
frecent(rank,
time
) {
# relate frequency and time
dx = t -
time
if
( dx < 3600 )
return
rank * 4
if
( dx < 86400 )
return
rank * 2
if
( dx < 604800 )
return
rank / 2
return
rank / 4
}
function
output(files, out, common) {
# list or return the desired directory
if
( list ) {
cmd =
"sort -n >&2"
for
( x
in
files ) {
if
( files[x] )
printf
"%-10s %s\n"
, files[x], x | cmd
}
if
( common ) {
printf
"%-10s %s\n"
,
"common:"
, common >
"/dev/stderr"
}
}
else
{
if
( common ) out = common
print out
}
}
function
common(matches) {
# find the common root of a list of matches, if it exists
for
( x
in
matches ) {
if
( matches[x] && (!short || length(x) < length(short)) ) {
short = x
}
}
if
( short ==
"/"
)
return
# use a copy to escape special characters, as we want to return
# the original. yeah, this escaping is awful.
clean_short = short
gsub(/\[\(\)\[\]\|\]/,
"\\\\&"
, clean_short)
for
( x
in
matches )
if
( matches[x] && x !~ clean_short )
return
return
short
}
BEGIN {
gsub(
" "
,
".*"
, q)
hi_rank = ihi_rank = -9999999999
}
{
if
( typ ==
"rank"
) {
rank = $2
}
else
if
( typ ==
"recent"
) {
rank = $3 - t
}
else
rank = frecent($2, $3)
if
( $1 ~ q ) {
matches[$1] = rank
}
else
if
( tolower($1) ~ tolower(q) ) imatches[$1] = rank
if
( matches[$1] && matches[$1] > hi_rank ) {
best_match = $1
hi_rank = matches[$1]
}
else
if
( imatches[$1] && imatches[$1] > ihi_rank ) {
ibest_match = $1
ihi_rank = imatches[$1]
}
}
END {
# prefer case sensitive
if
( best_match ) {
output(matches, best_match, common(matches))
}
else
if
( ibest_match ) {
output(imatches, ibest_match, common(imatches))
}
}
')"
[ $? -
eq
0 ] && [
"$cd"
] && {
if
[
"$echo"
];
then
echo
"$cd"
;
else
builtin
cd
"$cd"
;
fi
}
fi
}
alias
${_Z_CMD:-z}=
'_z 2>&1'
[
"$_Z_NO_RESOLVE_SYMLINKS"
] || _Z_RESOLVE_SYMLINKS=
"-P"
if
type
compctl >
/dev/null
2>&1;
then
# zsh
[
"$_Z_NO_PROMPT_COMMAND"
] || {
# populate directory list, avoid clobbering any other precmds.
if
[
"$_Z_NO_RESOLVE_SYMLINKS"
];
then
_z_precmd() {
(_z --add
"${PWD:a}"
&)
}
else
_z_precmd() {
(_z --add
"${PWD:A}"
&)
}
fi
[[ -n
"${precmd_functions[(r)_z_precmd]}"
]] || {
precmd_functions[$(($
#precmd_functions+1))]=_z_precmd
}
}
_z_zsh_tab_completion() {
# tab completion
local
compl
read
-l compl
reply=(${(f)
"$(_z --complete "
$compl
")"
})
}
compctl -U -K _z_zsh_tab_completion _z
elif
type
complete >
/dev/null
2>&1;
then
# bash
# tab completion
complete -o filenames -C
'_z --complete "$COMP_LINE"'
${_Z_CMD:-z}
[
"$_Z_NO_PROMPT_COMMAND"
] || {
# populate directory list. avoid clobbering other PROMPT_COMMANDs.
grep
"_z --add"
<<<
"$PROMPT_COMMAND"
>
/dev/null
|| {
PROMPT_COMMAND=
"$PROMPT_COMMAND"
$
'\n'
'(_z --add "$(command pwd '
$_Z_RESOLVE_SYMLINKS
' 2>/dev/null)" 2>/dev/null &);'
}
}
fi
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK