-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfindfile.sh
executable file
·157 lines (136 loc) · 3.08 KB
/
findfile.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# Such srcipt accepted a file name, and determine where such file can be reach from current working path as parent directory
# Note:
# - if there exists several paths, only 1 of them will show
# - if there no such path, the original path after symbol link expand will show
declare -a ans
declare -a softLinkList
declare -A pathLinkMap
srcFileName=
# In order to switch debug output easily, define the variable dbg_echo
# dbg_echo=echo
dbg_echo="eval # ||"
function show_answer_and_exit()
{
echo "$1"
exit 0
}
function show_useage_and_exit()
{
if [[ -n "$1" ]]
then
echo "$1" >&2
fi
cat >&2 <<-USAGE
Usage: $0 [file]
USAGE
exit -1
}
function show_error_and_exit()
{
echo "$1" >&2
exit -1
}
function try_the_link_path()
{
$dbg_echo -n "$1 -v.s.- $2: "
if [[ "$1" == "$2"* ]]
then
$dbg_echo "Pass"
return 1
else
$dbg_echo "Fail"
return 0
fi
}
# $1 is the softlink
# The softlink list and linkpath map might updated
function handle_a_link()
{
local curLink="$1"
local curLinkPath="$(readlink -f "$curLink")"
$dbg_echo "handling: $curLink --> $curLinkPath"
if [[ -d "$curLinkPath" ]]
then
try_the_link_path "$srcFileName" "$curLinkPath"
if [[ $? -eq 1 ]]
then
local ansPath="${curLink##"$curPath/"}${fileName##"$curLinkPath"}"
if [[ ! -n "$ansPath" ]]
then
ansPath="."
fi
show_answer_and_exit "$ansPath"
fi
if [[ ! -n "${pathLinkMap[$curLinkPath]}" ]]
then
$dbg_echo "find and add new link from path: $curLinkPath: ${pathLinkMap[$curLinkPath]}"
add_links_from_a_path "$curLinkPath"
pathLinkMap["$curLinkPath"]="$curLink" # If need to support multipath, this should use array list
fi
fi
}
function add_links_from_a_path()
{
local curPath="$1"
readarray -d $'\0' tmparray < <(find "$curPath" -type l -print0)
softLinkList=("${softLinkList[@]}" "${tmparray[@]}")
$dbg_echo "current linklist of ($curPath): ""${softLinkList[@]}"
}
function search_links_of_path()
{
local curPath="$1"
add_links_from_a_path "$curPath"
local i=0
while [[ $i < ${#softLinkList[@]} ]]
do
handle_a_link "${softLinkList[$i]}"
((i=$i+1))
done
return 1
}
function is_file_in_path()
{
local file="$1"
local curPath="$2"
if [[ "$file" == "$curPath"* ]]
then
return 1
fi
local absFileDir="$(cd "$(dirname "$fileName")" && pwd)"
local absCurPath="$(cd "$curPath" && pwd)"
if [[ "$absFileDir" == "$absCurPath"* ]]
then
return 1
fi
return 0
}
fileName="$1"
curPath="$PWD"
if [[ ! -a "$fileName" ]]
then
# output error message to standard error
if [[ -n "$fileName" ]]
then
show_useage_and_exit "Error: Bad file name: $1"
else
show_useage_and_exit "Error: Please input a file"
fi
fi
is_file_in_path "$fileName" "$curPath"
if [[ $? -eq 1 ]]
then
show_answer_and_exit "$fileName"
elif [[ -L "$fileName" ]] # If it is symbol link, then expand to target, such that the call of dirname will work OK
then
srcFileName="$(readlink "$fileName")"
is_file_in_path "$srcFileName" "$curPath"
if [[ $? -eq 1 ]]
then
show_answer_and_exit "$srcFileName"
fi
else
srcFileName="$fileName"
fi
search_links_of_path "$curPath"
ans=("$1")
show_answer_and_exit "${ans[@]}"