improved and modernised file functions
This commit is contained in:
@@ -35,32 +35,85 @@
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# expandlist : treat wildcards in a file/directory list
|
# Expand wildcards in a file/directory list and quote the results
|
||||||
# Usage: expandlist <item1 [item2 ... itemN]>
|
# Usage: expandlist [options] <item1 [item2 ... itemN]>
|
||||||
expandlist()
|
expandlist()
|
||||||
{
|
{
|
||||||
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
|
local separator=" "
|
||||||
printf "expandlist: Wraps a list of items in double quotes.\n\n"
|
local PARSED
|
||||||
printf "Usage: expandlist <item1 [item2 ... itemN]>\n\n"
|
|
||||||
|
PARSED=$(getopt -o hs:n --long help,separator:,newline -n 'expandlist' -- "$@")
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
disp E "Invalid options, use \"expandlist --help\" to display usage."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
eval set -- "$PARSED"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help)
|
||||||
|
printf "expandlist: expand globs and wrap matched items in double quotes.\n\n"
|
||||||
|
printf "Usage: expandlist [options] <item1 [item2 ... itemN]>\n\n"
|
||||||
printf "Options:\n"
|
printf "Options:\n"
|
||||||
printf "\t-h, --help\t\tDisplay this help screen\n"
|
printf "\t-h, --help\t\tDisplay this help screen\n"
|
||||||
|
printf "\t-s, --separator SEP\tSet output separator (default: space)\n"
|
||||||
|
printf "\t-n, --newline\t\tUse a newline as separator\n"
|
||||||
return 0
|
return 0
|
||||||
|
;;
|
||||||
|
-s|--separator)
|
||||||
|
separator="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-n|--newline)
|
||||||
|
separator=$'\n'
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
disp E "Invalid options, use \"expandlist --help\" to display usage."
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
local item="" result="" matched=0
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
for item in "$@"; do
|
||||||
|
local expanded=()
|
||||||
|
|
||||||
|
# True glob expansion when wildcards are present.
|
||||||
|
if [[ "$item" == *'*'* || "$item" == *'?'* || "$item" == *'['* ]]; then
|
||||||
|
expanded=( $item )
|
||||||
|
else
|
||||||
|
expanded=( "$item" )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local result=""
|
if [[ ${#expanded[@]} -eq 0 ]]; then
|
||||||
for item in "$@"; do
|
continue
|
||||||
for content in "$item"; do
|
fi
|
||||||
result+="\"$content\" "
|
|
||||||
|
for content in "${expanded[@]}"; do
|
||||||
|
if (( matched )); then
|
||||||
|
result+="$separator"
|
||||||
|
fi
|
||||||
|
result+="\"$content\""
|
||||||
|
matched=1
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
echo $result
|
|
||||||
|
shopt -u nullglob
|
||||||
|
printf '%s\n' "$result"
|
||||||
}
|
}
|
||||||
export -f expandlist
|
export -f expandlist
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Clean a directory or a tree from temporary or backup files
|
# Clean a directory tree from temporary or backup files
|
||||||
# Usage: clean [options] [directory1] [...[directoryX]]
|
# Usage: clean [options] [directory1] [...[directoryX]]
|
||||||
# Options:
|
# Options:
|
||||||
# -h, --help: display help screen
|
# -h, --help: display help screen
|
||||||
@@ -85,7 +138,7 @@ clean()
|
|||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-r|--recurs)
|
-r|--recurs)
|
||||||
local recursive=1
|
recursive=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-h|--help)
|
-h|--help)
|
||||||
@@ -100,11 +153,11 @@ clean()
|
|||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
-s|--shell)
|
-s|--shell)
|
||||||
local outshell=1
|
outshell=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-f|--force)
|
-f|--force)
|
||||||
local force=1
|
force=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
@@ -114,6 +167,7 @@ clean()
|
|||||||
*)
|
*)
|
||||||
disp E "Invalid parameter, use \"clean --help\" to display options list"
|
disp E "Invalid parameter, use \"clean --help\" to display options list"
|
||||||
return 1
|
return 1
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -121,21 +175,24 @@ clean()
|
|||||||
local dirlist=("$@")
|
local dirlist=("$@")
|
||||||
[[ ${#dirlist[@]} -eq 0 ]] && dirlist=(".")
|
[[ ${#dirlist[@]} -eq 0 ]] && dirlist=(".")
|
||||||
|
|
||||||
local findopt=() rmopt
|
local findopt=() rmopt=()
|
||||||
[[ ! $recursive ]] && findopt=(-maxdepth 1)
|
(( ! recursive )) && findopt=(-maxdepth 1)
|
||||||
[[ ! $force ]] && rmopt="-i"
|
(( ! force )) && rmopt=(-i)
|
||||||
unset recursive force
|
|
||||||
|
|
||||||
for dir in $dirlist; do
|
for dir in "${dirlist[@]}"; do
|
||||||
find "$dir" "${findopt[@]}" -type f \( -name "*~" -o -name "#*#" -o -name "*.bak" -o -name ".~*#" \) -print0 | while IFS= read -r -d '' f; do
|
find "$dir" "${findopt[@]}" -type f \( -name "*~" -o -name "#*#" -o -name "*.bak" -o -name ".~*#" \) -print0 |
|
||||||
if [[ ! $outshell ]]; then
|
while IFS= read -r -d '' f; do
|
||||||
rm $rmopt $f
|
if (( outshell )); then
|
||||||
|
if (( ${#rmopt[@]} )); then
|
||||||
|
printf 'rm %s -- "%s"\n' "${rmopt[*]}" "$f"
|
||||||
else
|
else
|
||||||
echo "rm $rmopt $f"
|
printf 'rm -- "%s"\n' "$f"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
rm "${rmopt[@]}" -- "$f"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
unset outshell dirlist dellist findopt rmopt
|
|
||||||
}
|
}
|
||||||
export -f clean
|
export -f clean
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -168,7 +225,7 @@ export -f mcd
|
|||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Rename all files in current directory to replace spaces with _
|
# Rename files and directories to replace spaces with another character
|
||||||
# Usage: rmspc [options]
|
# Usage: rmspc [options]
|
||||||
# Options:
|
# Options:
|
||||||
# -h, --help: display help screen
|
# -h, --help: display help screen
|
||||||
@@ -178,8 +235,11 @@ export -f mcd
|
|||||||
# -s, --shell: do nothing and display commands that would be executed
|
# -s, --shell: do nothing and display commands that would be executed
|
||||||
rmspc()
|
rmspc()
|
||||||
{
|
{
|
||||||
local lst=""
|
local recurs=0 verb=0 shell=0
|
||||||
|
local substchar="_" substchar_set=0
|
||||||
|
local mvopt=()
|
||||||
local PARSED
|
local PARSED
|
||||||
|
|
||||||
PARSED=$(getopt -o hr:c::vs --long help,recursive,subst-char::,verbose,shell -n 'rmspc' -- "$@")
|
PARSED=$(getopt -o hr:c::vs --long help,recursive,subst-char::,verbose,shell -n 'rmspc' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
disp E "Invalid options, use \"rmspc --help\" to display usage."
|
disp E "Invalid options, use \"rmspc --help\" to display usage."
|
||||||
@@ -203,27 +263,20 @@ rmspc()
|
|||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
-r|--recursive)
|
-r|--recursive)
|
||||||
local recurs=1
|
recurs=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-c|--subst-char)
|
-c|--subst-char)
|
||||||
# Handle optional argument for short/long options
|
substchar_set=1
|
||||||
case "$2" in
|
|
||||||
"")
|
|
||||||
substchar=""
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
substchar="$2"
|
substchar="$2"
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-v|--verbose)
|
-v|--verbose)
|
||||||
local verb=1
|
verb=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-s|--shell)
|
-s|--shell)
|
||||||
local shell=1
|
shell=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
@@ -232,49 +285,58 @@ rmspc()
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
disp E "Invalid parameter, use \"rmspc --help\" to display options list"
|
disp E "Invalid parameter, use \"rmspc --help\" to display options list"
|
||||||
echo
|
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
[[ ! $substchar ]] && substchar="_"
|
[[ "$substchar" == "none" ]] && substchar=""
|
||||||
[[ $substchar == "none" ]] && local substchar=""
|
(( verb )) && mvopt=(-v)
|
||||||
[[ $verb ]] && local mvopt="-v"
|
|
||||||
|
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
for f in *; do
|
for f in *; do
|
||||||
[[ $recurs ]] && [[ -d "$f" ]] && (
|
if (( recurs )) && [[ -d "$f" ]]; then
|
||||||
[[ $verb ]] && disp I "Entering directory $(pwd)/$f ..."
|
(
|
||||||
local lastdir=$f
|
local lastdir=$f
|
||||||
pushd "$f" >/dev/null
|
(( verb )) && disp I "Entering directory $(pwd)/$f ..."
|
||||||
rmspc ${recurs:+-r} ${substchar:+-c "$substchar"} ${verb:+-v} ${shell:+-s}
|
pushd "$f" >/dev/null || exit 1
|
||||||
popd >/dev/null
|
|
||||||
[[ $verb ]] && disp I "Leaving directory $(pwd)/$lastdir"
|
if (( substchar_set )); then
|
||||||
unset lastdir
|
rmspc ${recurs:+-r} -c "$substchar" ${verb:+-v} ${shell:+-s}
|
||||||
|
else
|
||||||
|
rmspc ${recurs:+-r} ${verb:+-v} ${shell:+-s}
|
||||||
|
fi
|
||||||
|
|
||||||
|
popd >/dev/null || exit 1
|
||||||
|
(( verb )) && disp I "Leaving directory $(pwd)/$lastdir"
|
||||||
)
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$f" == *" "* ]]; then
|
if [[ "$f" == *" "* ]]; then
|
||||||
local newf="${f// /${substchar}}"
|
local newf="${f// /${substchar}}"
|
||||||
[[ "$f" == "$newf" ]] && continue # protection but should never happen
|
[[ "$f" == "$newf" ]] && continue
|
||||||
if [[ -n $shell ]]; then
|
if (( shell )); then
|
||||||
echo "mv ${mvopt:+$mvopt }\"$f\" \"$newf\""
|
if (( ${#mvopt[@]} )); then
|
||||||
|
printf 'mv %s -- "%s" "%s"\n' "${mvopt[*]}" "$f" "$newf"
|
||||||
else
|
else
|
||||||
mv ${mvopt:+$mvopt} "$f" "$newf" || {
|
printf 'mv -- "%s" "%s"\n' "$f" "$newf"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
mv "${mvopt[@]}" -- "$f" "$newf" || {
|
||||||
disp E "Failed renaming \"$f\" to \"$newf\"."
|
disp E "Failed renaming \"$f\" to \"$newf\"."
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
unset lst substchar verb shell newf command mvopt
|
shopt -u nullglob
|
||||||
}
|
}
|
||||||
export -f rmspc
|
export -f rmspc
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# display stats about a file structure
|
# Display statistics about a file tree
|
||||||
# Usage: file_stats [options] [path]
|
# Usage: file_stats [options] [path]
|
||||||
# Options:
|
# Options:
|
||||||
# -H, --human Human readable sizes\n"
|
# -H, --human Human readable sizes\n"
|
||||||
@@ -290,7 +352,7 @@ export -f rmspc
|
|||||||
# --max [size] Maximum size (e.g., 100M)
|
# --max [size] Maximum size (e.g., 100M)
|
||||||
file_stats()
|
file_stats()
|
||||||
{
|
{
|
||||||
local human=0 details=0 only_avg=0 only_med=0 only_count=0 only_total=0
|
local human=0 details=0 only_avg=0 only_med=0 only_count=0 only_total=0
|
||||||
local path="." show_all=1 ext_filter="" ext_list="" min_size="" max_size=""
|
local path="." show_all=1 ext_filter="" ext_list="" min_size="" max_size=""
|
||||||
|
|
||||||
local PARSED
|
local PARSED
|
||||||
@@ -387,12 +449,12 @@ local human=0 details=0 only_avg=0 only_med=0 only_count=0 only_total=0
|
|||||||
# Prepare find filters
|
# Prepare find filters
|
||||||
local find_cmd=(find "$path" -type f)
|
local find_cmd=(find "$path" -type f)
|
||||||
|
|
||||||
# Extension simple
|
# Single extension filter
|
||||||
if [[ -n "$ext_filter" ]]; then
|
if [[ -n "$ext_filter" ]]; then
|
||||||
find_cmd+=(-iname "*.$ext_filter")
|
find_cmd+=(-iname "*.$ext_filter")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Extension liste
|
# Extension list filter
|
||||||
if [[ -n "$ext_list" ]]; then
|
if [[ -n "$ext_list" ]]; then
|
||||||
IFS=',' read -ra exts <<< "$ext_list"
|
IFS=',' read -ra exts <<< "$ext_list"
|
||||||
find_cmd+=('(')
|
find_cmd+=('(')
|
||||||
@@ -403,7 +465,7 @@ local human=0 details=0 only_avg=0 only_med=0 only_count=0 only_total=0
|
|||||||
find_cmd+=(')')
|
find_cmd+=(')')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Taille min/max (à évaluer en octets)
|
# Minimum/maximum size filters (evaluated in bytes)
|
||||||
if [[ -n "$min_size" ]]; then
|
if [[ -n "$min_size" ]]; then
|
||||||
find_cmd+=(-size +"$(numfmt --from=iec "$min_size")"c)
|
find_cmd+=(-size +"$(numfmt --from=iec "$min_size")"c)
|
||||||
fi
|
fi
|
||||||
@@ -411,7 +473,7 @@ local human=0 details=0 only_avg=0 only_med=0 only_count=0 only_total=0
|
|||||||
find_cmd+=(-size -"$(( $(numfmt --from=iec "$max_size") + 1 ))"c)
|
find_cmd+=(-size -"$(( $(numfmt --from=iec "$max_size") + 1 ))"c)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Exécution
|
# Execution
|
||||||
"${find_cmd[@]}" -printf "%s\n" 2>/dev/null | sort -n | \
|
"${find_cmd[@]}" -printf "%s\n" 2>/dev/null | sort -n | \
|
||||||
awk -v human="$human" -v details="$details" -v only_avg="$only_avg" \
|
awk -v human="$human" -v details="$details" -v only_avg="$only_avg" \
|
||||||
-v only_med="$only_med" -v only_count="$only_count" \
|
-v only_med="$only_med" -v only_count="$only_count" \
|
||||||
@@ -512,10 +574,10 @@ export -f file_stats
|
|||||||
# -l : limit : number of files to return (default is 10)
|
# -l : limit : number of files to return (default is 10)
|
||||||
findbig()
|
findbig()
|
||||||
{
|
{
|
||||||
local details=0 limit=10 no_change=0 one_fs=0
|
local details=0 limit=10 one_fs=0
|
||||||
|
|
||||||
local PARSED
|
local PARSED
|
||||||
PARSED=$(getopt -o hd:l:x --long help,details,one-fs,limit: -n 'findbig' -- "$@")
|
PARSED=$(getopt -o hdl:x --long help,details,limit:,one-fs -n 'findbig' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
disp E "Invalid options, use \"findbig --help\" to display usage."
|
disp E "Invalid options, use \"findbig --help\" to display usage."
|
||||||
return 1
|
return 1
|
||||||
@@ -538,14 +600,18 @@ findbig()
|
|||||||
details=1
|
details=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-n|--no-change)
|
|
||||||
no_change=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-l|--limit)
|
-l|--limit)
|
||||||
limit="$2"
|
limit="$2"
|
||||||
|
[[ "$limit" =~ ^[0-9]+$ ]] || {
|
||||||
|
disp E "Invalid limit: must be a positive integer."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
-x|--one-fs)
|
||||||
|
one_fs=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--)
|
--)
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
@@ -560,13 +626,16 @@ findbig()
|
|||||||
local dir="${1:-.}"
|
local dir="${1:-.}"
|
||||||
|
|
||||||
# Prepare find arguments in an array for cleaner handling
|
# Prepare find arguments in an array for cleaner handling
|
||||||
local find_args=("-L" "$dir" "-type" "f")
|
local find_args=(-L "$dir")
|
||||||
(( one_fs )) && find_args+=("-xdev")
|
(( one_fs )) && find_args+=(-xdev)
|
||||||
|
find_args+=(-type f)
|
||||||
|
|
||||||
# Logic: find files, print size and path, sort numeric reverse, take N
|
# Logic: find files, print size and path, sort numeric reverse, take N
|
||||||
if (( details )); then
|
if (( details )); then
|
||||||
find "${find_args[@]}" -printf "%s %p\n" 2>/dev/null | sort -rn | head -n "$limit" | while read -r size path; do
|
find "${find_args[@]}" -printf "%s %p\n" 2>/dev/null | sort -rn | head -n "$limit" |
|
||||||
ls -ld "$path"
|
while IFS= read -r line; do
|
||||||
|
local path="${line#* }"
|
||||||
|
ls -ld -- "$path"
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
find "${find_args[@]}" -printf "%s %p\n" 2>/dev/null | sort -rn | head -n "$limit"
|
find "${find_args[@]}" -printf "%s %p\n" 2>/dev/null | sort -rn | head -n "$limit"
|
||||||
@@ -586,7 +655,7 @@ export -f findbig
|
|||||||
# --delete : delete empty files and display their paths
|
# --delete : delete empty files and display their paths
|
||||||
findzero()
|
findzero()
|
||||||
{
|
{
|
||||||
local delete=0 details=0 one_fs=0 no_change=0
|
local delete=0 details=0 one_fs=0
|
||||||
|
|
||||||
local PARSED
|
local PARSED
|
||||||
# o: options, long: long equivalents
|
# o: options, long: long equivalents
|
||||||
@@ -660,7 +729,7 @@ export -f findzero
|
|||||||
# --delete : delete dead links and display their paths
|
# --delete : delete dead links and display their paths
|
||||||
finddead()
|
finddead()
|
||||||
{
|
{
|
||||||
local delete=0 details=0 one_fs=0 no_change=0
|
local delete=0 details=0 one_fs=0
|
||||||
|
|
||||||
local PARSED
|
local PARSED
|
||||||
PARSED=$(getopt -o hdx --long help,details,one-fs,delete -n 'finddead' -- "$@")
|
PARSED=$(getopt -o hdx --long help,details,one-fs,delete -n 'finddead' -- "$@")
|
||||||
|
|||||||
Reference in New Issue
Block a user