-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathrch.sh
executable file
·273 lines (243 loc) · 6.92 KB
/
rch.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
#!/usr/bin/env bash
# rch - CLI tool to replace characters on a set of files
#
# Replace character(s) with another one character(s)
# in a set of files given on a directory
#
# @param -o The old string to replace
# e.g. "xyz"
# @param -n The new string that replaces the old one
# e.g. "abc"
# @param -d The directory where the files to process are. Full or relative path
# e.g. "/home/you/foo/"
# @param -p The pattern of the files to process. Only full path. Ommited if directory provided
# e.g. "/home/you/foo/*.txt"
# @param -b [OPTIONAL] A directory to place backups of every processed file. Full or relative path
# e.g. "/home/you/backup/foo"
#
# Credit where it's due.
# @author Lucio Martínez <luciomartinez@openmailbox.org>
readonly PACKAGE="rch"
readonly VERSION="0.1"
verbose=false
# Print message only if verbose mode is enabled
log() {
[ $verbose == true ] && echo "$*" ||:
}
print_help() {
echo "Usage: $PACKAGE [OPTION]... -o TARGET -n SOURCE -d DIRECTORY -p PATH [-b BACKUP]"
echo "Replace character(s) TARGET with character(s) SOURCE in the files on DIRECTORY or PATH."
echo " "
echo " -n, --new new string that replaces the old one"
echo " -o, --old old string that will be replaced"
echo " -d, --directory directory of files to be processed"
echo " -p, --pattern pattern of the files to be processed"
echo " -b, --backup make a backup of each file processed on the BACKUP directory"
echo " -h, --help display this help and exit"
echo " --version output version information and exit"
echo " -v, --verbose explain what is being done"
}
print_version() {
echo "$PACKAGE $VERSION"
}
# @param error message
print_error() {
echo "$PACKAGE: $*"
echo "Try '$PACKAGE --help' for more information."
}
# @param relative or fullpath
# @returns the full path of the path entered
get_full_path() {
echo `readlink -f $*` # Hum, so you know a better way to return on bash..
}
# @param fullpath
create_directory_if_not_exists() {
if [ ! -d $* ];
then
log " [+] Backup directory does not exist, creating it on '$BACKUP_DIR'..."
mkdir -p "$*"
fi
}
# DISABLED FUNCTION
# Reason: shouldn't the OS free the /tmp folder when needed?
#
# Remove every useles file generated by the application
# but do NOT remove the backup files generated intentionally
# remove_obsolete_files() {
# rm $temp_file
# }
# @param 1. Old string to be replace
# @param 2. New string to replace old
# @param 3. File where string will be replaced
# @param 4. Temporary file to prevent data corruption (I am feeling optimistic)
replace_string_on_file() {
log " [+] Replacing string '$1' with '$2' on file '$3'..."
# Replace the strings on the file
sed "s/$1/$2/g" "$3" > "$4" && mv "$4" "$3"
}
# @param 1. Old string stored on the file(s) to be replaced
# @param 2. New string that will replace the old one
# @param 3. Directory where the file to process are
# @param 4. Pattern with a full path to the files to process (not used if Directory given)
# @param 5. Backup directory where each processed file will be copied (use value 0 for not backup)
# @param 6. ??
# @param 7. And of course, profit!
start_working() {
local old="$1"
local new="$2"
local directory="$3"
local pattern="$4"
local target_dir='';
local f;
local readonly BACKUP_DIR="$5";
local readonly INITIAL_DIR="$(get_full_path '.')";
local readonly TEMP_FILE="/tmp/out.tmp.$$";
# If backup is required, the directory has to exist
if [ "$BACKUP_DIR" != 0 ];
then
create_directory_if_not_exists "$BACKUP_DIR"
# Process using the full path of the directory
BACKUP_DIR="$(get_full_path $BACKUP_DIR)";
fi
# If directory *and* pattern were given simoultaneusly
# we are going to use directory only.
# If you think I'm wrong, change it ;)
if [ "$directory" != 0 ];
then
# Get the full path of the target directory
target_dir="$(get_full_path $directory)"
# Change directory temporarily to the target
cd $target_dir
# Iterate over the files on the target directory
pattern="`ls -A $target_dir`"
fi
# For every file in the pattern..
for f in $pattern;
do
# Do nothing when processing the node to the actual directory
# That is called '.' (yep, a dot) on linux
if [ "$f" != '.' ];
then
# Check if it is a regular file
# can be readable and writable
if [ -f "$f" -a -r "$f" -a -w "$f" ];
then
log " [+] Processing file '$f'..."
# Check if we need to make a backup
if [ "$BACKUP_DIR" != 0 ];
then
# Now, please, do the backup
log " [+] Making backup of file '$f'..."
cp "$f" "$BACKUP_DIR"
fi
replace_string_on_file "$old" "$new" "$f" "$TEMP_FILE"
else
log " [-] WARNING: Cannot process file '$f'"
fi
fi
done
# Just in case, we go to the initial directory of the script
cd $INITIAL_DIR;
}
main() {
# Define required parameters here
local r_new=0
local r_old=0
local r_target=0
# Passed values
local backup_dir=0
local s_new=''
local s_old=''
local target_directory=0
local target_pattern=0
#getopts
while test $# -gt 0; do
case "$1" in
-h|--help)
print_help
exit 0
;;
--version)
print_version
exit 0
;;
-v|--verbose)
shift
verbose=true
shift
;;
-b|--backup)
shift
if test $# -gt 0;
then
backup_dir="$1"
else
print_error "No backup directory specified"
exit 1
fi
shift
;;
-d|--directory)
shift
if test $# -gt 0;
then
target_directory="$1"
r_target=1
else
print_error "No directory specified"
exit 1
fi
shift
;;
-n|--new)
shift
if test $# -gt 0;
then
s_new="$1"
r_new=1
else
print_error "No new string specified"
exit 1
fi
shift
;;
-o|--old)
shift
if test $# -gt 0;
then
s_old="$1"
r_old=1
else
print_error "No old string specified"
exit 1
fi
shift
;;
-p|--pattern)
shift
if test $# -gt 0;
then
target_pattern="$1"
r_target=1
else
print_error "No pattern specified"
exit 1
fi
shift
;;
*)
print_error "invalid option: '$1'"
exit 1
;;
esac
done
# Check if all parameters were entered
if [ "$r_old" != 1 -o "$r_new" != 1 -o "$r_target" != 1 ]
then
print_error "missing required operands"
exit 1
fi
# Everything is ok.. Now lets work!
start_working "$s_old" "$s_new" "$target_directory" "$target_pattern" "$backup_dir"
}
main "$@"