Dotaz na LLamu
Když se do deklarované bash funkce pro účely ~/.profile uvede pole, bude se toto pole načítat při každém volání funkce z terminálu, nebo lze pole uvnitř funkce nadeklarovat tak, aby zůstalo po celou dobu běhu terminálu a nevynulovalo se? Příklad. Nadefinujme funkci rmh, která bude předávat argumenty příkazu rm , ale bude wrapovací funkcí, která kontroluje bezpečnost argumentů. Například pokud argumenty obsahují relativní cestu, nebude povoleno spuštění rm. Dále bych deklaroval pole s adresáři, u kterých by bylo určena jejich důležitost podle minimálního počtu vyžadovaných adresářů v argumentu cesty. Např. pokud spustím rmh ~/Obrázky/*.jpg, bude se vyžadovat ještě min. jeden adresář v cestě, takže rm se nespustí. Aby se rm spustilo musela by cesta vypadat např. takto ~/Obrázky/designer/*.jpg , toto nastavení by bylo individuální podle toho v jakém adresáři se budu vyskytovat a specifikace by byla v tom poli.
V bashi je možné definovat pole uvnitř funkce tak, aby zůstalo po celou dobu běhu terminálu a nevynulovalo se. Jedním ze způsobů, jak toho dosáhnout, je použít deklaraci declare
s atributem -g
(globální) pro pole.
Příklad:
bash
rmh() {
local -g important_dirs=(~/Obrázky ~/Dokumenty ~/Projekty)
local -g min_dirs_required=(~/Obrázky 2 ~/Dokumenty 1 ~/Projekty 3)
# Kontrola bezpečnost argumentů
for arg in "$@"; do
if [[ $arg =~ ^\. ]]; then
echo "Relativní cesta není povolena"
return 1
fi
done
# Kontrola minimálního počtu adresářů v cestě
for dir in "${important_dirs[@]}"; do
if [[ $1 =~ $dir ]]; then
local min_dirs=${min_dirs_required[$dir]}
local dirs_in_path=$(echo "$1" | tr '/' '\n' | wc -l)
if (( dirs_in_path < min_dirs )); then
echo "Minimální počet adresářů v cestě nebyl splněn"
return 1
fi
fi
done
# Spuštění příkazu rm
rm "$@"
}
ROZŠÍŘENÁ VERZE NAHRAZUJE ~ ZA DOMOVSKÝ ADRESÁŘ:
declare -g
important_dirs=(~/Obrázky ~/Dokumenty ~/Projekty)
declare -g
min_dirs_required=(~/Obrázky 2 ~/Dokumenty 1 ~/Projekty 3) expand_path() { if [[ $1 == ~* ]]; then echo "${1/#\~/$HOME}" else echo "$1" fi }
rmh
() {
for arg in "$@"; do
if [[ $arg =~ ^\. ]]; then echo "Relativní cesta není povolena" return 1 fi
done
for dir in "${important_dirs[@]}"; do
expanded_dir=$(expand_path "$dir") expanded_arg=$(expand_path "$1")
if [[ $1 =~ $dir ]]; then
local min_dirs=${min_dirs_required[$dir]}
local
dirs_in_path=$(echo "$1" | tr '/' '\n' | wc -l)
if (( dirs_in_path < min_dirs )); then echo "Minimální počet adresářů v cestě nebyl splněn" return 1 fi
fi done
rm "$@"
}
2. ROZŠÍŘENÁ VERZE
# @TODO: Opravit logiku a scházející proměnné:
#declare -g
important_dirs=(~/Obrázky ~/Dokumenty ~/Projekty)#declare -g
min_dirs_required=(~/Obrázky 2 ~/Dokumenty 1 ~/Projekty 3)
# Nové proměnné - @TODO: Implement
declare -g image_dirs=(~/Obrázky ~/Pictures ~/Fotky ~/Photo ~/Photos)
declare -g music_dirs=(~/Music ~/Hudba)
declare -g video_dirs=(~/Video ~/Videa ~/Videos)
declare -g document_dirs=(~/Documents ~/Dokumenty)
declare -g download_dirs=(~/Stažené ~/Downloads ~/Downloaded)
declare -g script_dirs=(~/Skripty ~/Scripts)
declare -g www_dirs=(~/www ~/www_projects)
declare -g pascal_dirs=(~/FreePascal)
# Povolené přípony souborů
declare -g image_extensions=("*.jpg" "*.jpeg" "*.png" "*.gif" "*.bmp" "*.svg" "*.ico")
declare -g music_extensions=("*.wav" "*.mp3" "*.m3u")
declare -g video_extensions=("*.avi" "*.mp4" "*.mov" "*.m4p")
declare -g document_extensions=("*.txt" "*.doc" "*.docx" "*.xls" "*.xlsx" "*.ppt" "*.pptx" "*.odt" "*.ods" "*.odp")
declare -g download_extensions=("*.zip" "*.tar" "*.gz" "*.bz2")
declare -g script_extensions=("*.sh" "*.py" "*.pl")
declare -g www_extensions=("*.js" "*.php" "*.txt" "*.jpg" "*.jpeg" "*.png" "*.gif" "*.bmp")
declare -g pascal_extensions=("*.pas" "*.lpr" "*.ppu" "*.o" "*.compiled")
declare -g rm_options=(
"-f" "--force" "-i" "-I" "--interactive" "--one-file-system"
"--no-preserve-root" "--preserve-root" "-r" "-R" "--recursive"
"-d" "--dir" "-v" "--verbose" "--help" "-h" "--version"
)
# @TODO: Implement: how old files will be deleted
# -old - if older then yesterday
# -
today-
old-versions - specify latest file name which will not be deleted - exmaple: record_0021.avi should delete older versions of this file, today.
declare -g special_options=(
"-old" "-yesterday" "-today" "-24h" "-2days" "old-versions-now"
)
expand_path() { if [[ $1 == ~* ]]; then echo "${1/#\~/$HOME}" else echo "$1" fi }
rmh
() {
for arg in "$@"; do
if [[ $arg =~ ^\. ]]; then echo "Relativní cesta není povolena" return 1 fi
done
for dir in "${important_dirs[@]}"; do
# Pokud je argument volbou pro rm, přeskočí kontrolu
if
[[ " ${rm_options[@]} " =~ " ${arg} " ]]; then
continue
fi
expanded_dir=$(expand_path "$dir")
expanded_arg=$(expand_path "$1")
# Kontrola, zda argument začíná domovskou složkou uživatele
if
[[ ! $expanded_arg =~ ^$HOME ]]; then
echo "Povoleno je pouze mazání souborů v domovském adresáři uživatele."
return 1
fi
# Kontrola na nebezpečný znak '*'
if [[ $expanded_arg == $expanded_dir* ]]; then
# Kontrola na nebezpečný znak '*'
if [[ $arg =~ \* ]]; then
# Kontrola, zda je název dostatečně specifikovaný
if [[ $arg =~ \.[a-zA-Z0-9]+$ ]] || [[ $arg =~ [^*/]{3,}\* ]]; then
if [[ ${#arg} -lt 5 ]]; then
# Pokud je název souboru kratší než 5 znaků před koncovkou nebo hvězdičkou
local file_count=$(ls "$arg" 2>/dev/null | wc -l)
if (( file_count > 0 )); then
echo -e "\e[33mPočet souborů, které budou smazány: $file_count\e[0m"
ls "$arg"
echo -e "\e[31mPozor: Argument obsahuje nebezpečný znak '*'. Opravdu chcete smazat soubory? [y/N]\e[0m"
read -r confirmation
if [[ $confirmation != "y" ]]; then
echo "Mazání zrušeno."
return 1
fi
else
echo "Žádné soubory nebyly nalezeny."
return 1
fi
fi
else
echo -e "\e[31mPozor: Argument obsahuje nebezpečný znak '*' a není dostatečně specifikován. Opravdu chcete smazat soubory? [y/N]\e[0m"
read -r confirmation
if [[ $confirmation != "y" ]]; then
echo "Mazání zrušeno."
return 1
fi
fi
fi
fi
if [[ $1 =~ $dir ]]; then
local min_dirs=${min_dirs_required[$dir]}
local
dirs_in_path=$(echo "$1" | tr '/' '\n' | wc -l)
if (( dirs_in_path < min_dirs )); then echo "Minimální počet adresářů v cestě nebyl splněn" return 1 fi
fi
# Zjištění, do které kategorie složek argument patří
for
dir in "${image_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
check_extension "$arg" "${image_extensions[@]}" || {
echo "Nepovolený typ souboru v obrázkové složce: $arg"
invalid_file=1
}
fi
done
# Pokračování pouze pokud nebyl nalezen neplatný soubor
if [[ ! $invalid_file -eq 1 ]]; then
for
dir in "${music_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${music_extensions[@]}"; then
echo "Nepovolený typ souboru v hudební složce: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for
dir in "${video_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${video_extensions[@]}"; then
echo "Nepovolený typ souboru ve video složce: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for
dir in "${document_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${document_extensions[@]}"; then
echo "Nepovolený typ souboru v dokumentové složce: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for
dir in "${download_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${download_extensions[@]}"; then
echo "Nepovolený typ souboru ve složce Stažené: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for
dir in "${script_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${script_extensions[@]}"; then
echo "Nepovolený typ souboru ve složce Skripty: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for
dir in "${www_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${www_extensions[@]}"; then
echo "Nepovolený typ souboru ve složce WWW: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for
dir in "${pascal_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${pascal_extensions[@]}"]; then
echo "Nepovolený typ souboru ve složce FreePascal: $arg"
invalid_file=1
break
fi
fi
done
fi
# Dodatečná výzva pro citlivé přípony
if [[ ! $invalid_file -eq 1 ]]; then
for
ext in "${sensitive_extensions[@]}"; do
if [[ $arg == *"$ext" ]]; then
echo -e "\e[31mOpravdu chcete smazat soubory s příponou '$ext'? [y/N]\e[0m"
read -r confirmation
if [[ $confirmation != "y" ]]; then
echo "Mazání zrušeno."
return 1
fi
fi
done
fi
done
# Pokud byla nalezena jakákoli neplatná přípona, skript vrátí chybu
if [[ $invalid_file -eq 1 ]]; then
return 1
fi
rm "$@"
}
3. Rozšíření (pokus o implementaci)
Následný skript by měl zahrnovat rozšíření o implementaci kontroly stáří souboru (nezkontrolováno).
declare -g image_dirs=(~/Obrázky ~/Pictures ~/Fotky ~/Photo ~/Photos)
declare -g music_dirs=(~/Music ~/Hudba)
declare -g video_dirs=(~/Video ~/Videa ~/Videos)
declare -g document_dirs=(~/Documents ~/Dokumenty)
declare -g download_dirs=(~/Stažené ~/Downloads ~/Downloaded)
declare -g script_dirs=(~/Skripty ~/Scripts)
declare -g www_dirs=(~/www ~/www_projects)
declare -g pascal_dirs=(~/FreePascal)
# Povolené přípony souborů
declare -g image_extensions=("*.jpg" "*.jpeg" "*.png" "*.gif" "*.bmp" "*.svg" "*.ico")
declare -g music_extensions=("*.wav" "*.mp3" "*.m3u")
declare -g video_extensions=("*.avi" "*.mp4" "*.mov" "*.m4p")
declare -g document_extensions=("*.txt" "*.doc" "*.docx" "*.xls" "*.xlsx" "*.ppt" "*.pptx" "*.odt" "*.ods" "*.odp")
declare -g download_extensions=("*.zip" "*.tar" "*.gz" "*.bz2")
declare -g script_extensions=("*.sh" "*.py" "*.pl")
declare -g www_extensions=("*.js" "*.php" "*.txt" "*.jpg" "*.jpeg" "*.png" "*.gif" "*.bmp")
declare -g pascal_extensions=("*.pas" "*.lpr" "*.ppu" "*.o" "*.compiled")
declare -g rm_options=(
"-f" "--force" "-i" "-I" "--interactive" "--one-file-system"
"--no-preserve-root" "--preserve-root" "-r" "-R" "--recursive"
"-d" "--dir" "-v" "--verbose" "--help" "-h" "--version"
)
# Speciální možnosti pro kontrolu stáří souborů
declare -g special_options=(
"-old" "-yesterday" "-today" "-24h" "-2days" "old-versions-now"
)
expand_path() {
if [[ $1 == ~* ]]; then
echo "${1/#\~/$HOME}"
else
echo "$1"
fi
}
check_extension() {
local file=$1
shift
local valid_extensions=("$@")
for ext in "${valid_extensions[@]}"; do
if [[ $file == $ext ]]; then
return 0
fi
done
return 1
}
check_age_and_delete() {
local age=$1
local path=$2
local pattern=$3
find "$path" -type f -name "$pattern" -mtime "$age" -exec rm {} \;
}
rmh() {
invalid_file=0 # Proměnná pro sledování stavu neplatných souborů
for arg in "$@"; do
if [[ $arg =~ ^\. ]]; then
echo "Relativní cesta není povolena"
return 1
fi
expanded_arg=$(expand_path "$arg")
# Zpracování speciálních možností pro stáří souborů
if [[ " ${special_options[@]} " =~ " ${arg} " ]]; then
case $arg in
"-old")
check_age_and_delete "+1" "$expanded_arg" "*" # starší než včera
;;
"-yesterday")
check_age_and_delete "1" "$expanded_arg" "*" # přesně včera
;;
"-today")
check_age_and_delete "0" "$expanded_arg" "*" # starší než dnes
;;
"-24h")
find "$expanded_arg" -type f -mmin +1440 -exec rm {} \; # starší než 24 hodin
;;
"-2days")
check_age_and_delete "+2" "$expanded_arg" "*" # starší než 2 dny
;;
"old-versions-now")
# # -today-old-versions - specify latest file name which will not be deleted - exmaple: record_0021.avi should delete older versions of this file, today.
# @TODO: Tuto logiku bude třeba detailněji implementovat
;;
esac
continue
fi
# Zjištění, do které kategorie složek argument patří
for dir in "${image_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
check_extension "$arg" "${image_extensions[@]}" || {
echo "Nepovolený typ souboru v obrázkové složce: $arg"
invalid_file=1
}
fi
done
# Pokračování pouze pokud nebyl nalezen neplatný soubor
if [[ ! $invalid_file -eq 1 ]]; then
for dir in "${music_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${music_extensions[@]}"; then
echo "Nepovolený typ souboru v hudební složce: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for dir in "${video_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${video_extensions[@]}"; then
echo "Nepovolený typ souboru ve video složce: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for dir in "${document_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${document_extensions[@]}"; then
echo "Nepovolený typ souboru v dokumentové složce: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for dir in "${download_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${download_extensions[@]}"; then
echo "Nepovolený typ souboru ve složce Stažené: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for dir in "${script_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${script_extensions[@]}"; then
echo "Nepovolený typ souboru ve složce Skripty: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for dir in "${www_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${www_extensions[@]}"; then
echo "Nepovolený typ souboru ve složce WWW: $arg"
invalid_file=1
break
fi
fi
done
fi
if [[ ! $invalid_file -eq 1 ]]; then
for dir in "${pascal_dirs[@]}"; do
if [[ $expanded_arg =~ $dir ]]; then
if ! check_extension "$arg" "${pascal_extensions[@]}"]; then
echo "Nepovolený typ souboru ve složce FreePascal: $arg"
invalid_file=1
break
fi
fi
done
fi
# Dodatečná výzva pro citlivé přípony
if [[ ! $invalid_file -eq 1 ]]; then
for ext in "${sensitive_extensions[@]}"; do
if [[ $arg == *"$ext" ]]; then
echo -e "\e[31mOpravdu chcete smazat soubory s příponou '$ext'? [y/N]\e[0m"
read -r confirmation
if [[ $confirmation != "y" ]]; then
echo "Mazání zrušeno."
return 1
fi
fi
done
fi
done
# Pokud byla nalezena jakákoli neplatná přípona, skript vrátí chybu
if [[ $invalid_file -eq 1 ]]; then
return 1
fi
# Spuštění příkazu rm s argumenty
rm "$@"
}
Žádné komentáře:
Okomentovat