sobota 10. srpna 2024

wrapovací funkce pro rm (rmh) pro složky ~

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

Jak zkopírovat styly jako font a odstavec v LibreOffice Write?

V dokumentu Write píšu CV. Někde uprostřed mám nadpisy a chci zkopírovat jeden nadpis v četně stylů a vložit ho jinde. Když použiju např ct...

Štítky

.profile adm AI alfa transparence AND any aplikace asociativní pole atomicity audio awk bash benchmark bezpečnost biblehub BJT boolean buffering Cache-Conrol Cloudflare code Collector Cut-off colorpicker compare cookies css CSS3 curl cut čas data loss data lost data transfer reliability datasheet datetime.strptime development dioda diody EBO Emitter Cut-off Current ETag exclude exec Expires fflock fflush ffmpeg file read file write file_get_contents file_get_contents/file_put_contents file_put_contents filter find first_install.sh flock Fly-back dioda font-face fóra fotorezistor fread functions funkce fwrite gate gate drive geolokace gradient-background grep grub grub update hebrejština history hlavičky HS html html 5 https hudba charakterizace chroot ICES IGBT img sizes img srcset impedance implementace imshow inference inrush current install jalový výkon javascript javescript jednocení seznamů js kapacita součástek koeficient zesílení komunikace se serverem konfigurace Krita KSF Last-Modified lazy caching led LEFT JOIN librosa ligatury linux list log manuál masky matplotlib Max-Age measure memory měření MFCC MFCC koeficienty mint míry modules moralizace morphologie MOSFET mount moviepy mysql náběhový proud napěťová ochrana návod nel Network Error Logging NLP not nth-child oblékání ochrana okruhy přátel OpenVINO IR formát optočlen ořezové masky OSHB otázky otázky_jazyky otázky_moralismu_řešení parsování path personifikace photorec php php 4 php 5 php 6 php 7 php 8 phpbb phpBB3 pitch PN přechody pnp pole práva profilování program prune průraz přepěťová ochrana přepolování pseudokódd PWM regulátory pydub python python3 pytorch RBE RDSon read reaktance rectifier regulace vstupního napětí relyability remount replace restore reverzní geolokace RIGHT JOIN rm role rozvržení disků pro OS linux a data databází řešení samba sdílení Sec-Fetch-Dest Sec-Fetch-Mode Sec-Fetch-Site Sec-Fetch-User Secure Shell sed Set Cookie shunt schottka skript sloupce song sort soubory soundfile spínané zdroje spínání split SQL ssh stabilizace napětí stahování stream string strojové učení stropové učení syntax T5 tabulky tepelná ztráta test text-shadow thermal runaway time timestamp tkinter tr transistor transition tranzistor tranzistory tuple tvorba otázek TVS účiník update va charakteristika Vgs video Vth vynechání adresářů vývoj while wrapovací funkce XOR zdánlivý výkon zdroj zenerka zenerovo napětí zip zip archiv zkratky zpomalení zpracování textu Žalmy