diff --git a/topdir.sh b/topdir.sh index d3ec2fd..dfd753f 100755 --- a/topdir.sh +++ b/topdir.sh @@ -117,6 +117,13 @@ cleanup() { } trap cleanup EXIT +# Mostrar configuración si el formato es text +if [[ "$OUTPUT_FORMAT" == "text" ]]; then + echo "[topdir] Iniciando análisis..." + echo "[topdir] Directorio: $TARGET_DIR" + echo "[topdir] Algoritmo: $HASH_ALGO" +fi + pushd "$TARGET_DIR" >/dev/null || exit 1 # Definir snapshot relativo al directorio objetivo o usar el custom @@ -131,17 +138,27 @@ else pushd "$TARGET_DIR" >/dev/null || exit 1 fi +if [[ "$OUTPUT_FORMAT" == "text" ]]; then + echo "[topdir] Snapshot: $SNAPSHOT_FILE" +fi + # Leer patrones de exclusión desde archivo si existe if [[ -n "$IGNORE_FILE" && -f "$IGNORE_FILE" ]]; then while IFS= read -r pattern; do [[ -z "$pattern" || "$pattern" == \#* ]] && continue EXCLUDE_PATTERNS+=("$pattern") done < "$IGNORE_FILE" + if [[ "$OUTPUT_FORMAT" == "text" ]]; then + echo "[topdir] Cargadas ${#EXCLUDE_PATTERNS[@]} exclusiones desde $IGNORE_FILE" + fi elif [[ -f ".topdirignore" ]]; then while IFS= read -r pattern; do [[ -z "$pattern" || "$pattern" == \#* ]] && continue EXCLUDE_PATTERNS+=("$pattern") done < ".topdirignore" + if [[ "$OUTPUT_FORMAT" == "text" && ${#EXCLUDE_PATTERNS[@]} -gt 0 ]]; then + echo "[topdir] Cargadas ${#EXCLUDE_PATTERNS[@]} exclusiones desde .topdirignore" + fi fi # Construir comando find con exclusiones @@ -171,20 +188,35 @@ for pattern in "${EXCLUDE_PATTERNS[@]}"; do done # Generar nuevo snapshot: compute hash para cada archivo regular +if [[ "$OUTPUT_FORMAT" == "text" ]]; then + echo -n "[topdir] Escaneando archivos..." +fi + +file_count=0 while IFS= read -r -d '' file; do "$HASH_CMD" "$file" + file_count=$((file_count + 1)) + if [[ "$OUTPUT_FORMAT" == "text" && $((file_count % 100)) -eq 0 ]]; then + echo -ne "\r[topdir] Escaneando archivos... $file_count" + fi done < <("${find_cmd[@]}" -print0 | sort -z) > "$TMP_NEW" +if [[ "$OUTPUT_FORMAT" == "text" ]]; then + echo -e "\r[topdir] Escaneados $file_count archivos " +fi + # Si no hay snapshot previo, lo creamos y salimos if [[ ! -f "$SNAPSHOT_FILE" ]]; then mv "$TMP_NEW" "$SNAPSHOT_FILE" case "$OUTPUT_FORMAT" in text) - echo "Snapshot creado en '$SNAPSHOT_FILE' (no había ejecución previa)." + echo "[topdir] ✓ Snapshot creado en '$SNAPSHOT_FILE'" + echo "[topdir] ✓ $file_count archivos registrados" + echo "[topdir] Primera ejecución completada. Ejecuta nuevamente para detectar cambios." ;; json) - echo '{"status":"snapshot_created","snapshot_file":"'"$SNAPSHOT_FILE"'","new":[],"modified":[],"deleted":[]}' + echo '{"status":"snapshot_created","snapshot_file":"'"$SNAPSHOT_FILE"'","files_tracked":'"$file_count"',"new":[],"modified":[],"deleted":[]}' ;; csv) echo "status,path" @@ -197,6 +229,10 @@ fi # Convertir snapshot antiguo y nuevo a formato: \t # Convertir líneas "checksum path" a formato "pathchecksum" de forma robusta +if [[ "$OUTPUT_FORMAT" == "text" ]]; then + echo "[topdir] Comparando con snapshot anterior..." +fi + sed -E 's/^[[:space:]]*([0-9a-f]+)[[:space:]]+(.*)$/\2\t\1/' "$SNAPSHOT_FILE" > "$TMP_OLD" 2>/dev/null || true sed -E 's/^[[:space:]]*([0-9a-f]+)[[:space:]]+(.*)$/\2\t\1/' "$TMP_NEW" > "$TMP_NEW.sorted" mv "$TMP_NEW.sorted" "$TMP_NEW" @@ -229,29 +265,41 @@ done < "$TMP_OLD.changes" # Mostrar informe según formato case "$OUTPUT_FORMAT" in text) - echo "Informe de comparación para: $TARGET_DIR" + echo "" + echo "═══════════════════════════════════════════════════════════════" + echo " INFORME DE CAMBIOS" + echo "═══════════════════════════════════════════════════════════════" + echo "Directorio: $TARGET_DIR" + echo "Archivos escaneados: $file_count" + echo "Nuevos: ${#new_files[@]} | Modificados: ${#modified_files[@]} | Eliminados: ${#delete_files[@]}" + echo "───────────────────────────────────────────────────────────────" + echo "" if [[ ${#new_files[@]} -eq 0 && ${#modified_files[@]} -eq 0 && ${#delete_files[@]} -eq 0 ]]; then - echo "No se detectaron cambios desde la última ejecución." + echo "✓ No se detectaron cambios desde la última ejecución." else if [[ ${#new_files[@]} -gt 0 ]]; then - echo -e "\nNuevos archivos (${#new_files[@]}):" + echo "📄 NUEVOS ARCHIVOS (${#new_files[@]}):" for f in "${new_files[@]}"; do - echo " $f" + echo " + $f" done + echo "" fi if [[ ${#modified_files[@]} -gt 0 ]]; then - echo -e "\nArchivos modificados (${#modified_files[@]}):" + echo "✏️ ARCHIVOS MODIFICADOS (${#modified_files[@]}):" for f in "${modified_files[@]}"; do - echo " $f" + echo " ~ $f" done + echo "" fi if [[ ${#delete_files[@]} -gt 0 ]]; then - echo -e "\nArchivos eliminados desde último snapshot (${#delete_files[@]}):" + echo "🗑️ ARCHIVOS ELIMINADOS (${#delete_files[@]}):" for f in "${delete_files[@]}"; do - echo " $f" + echo " - $f" done + echo "" fi fi + echo "═══════════════════════════════════════════════════════════════" ;; json) @@ -281,7 +329,8 @@ case "$OUTPUT_FORMAT" in done del_json+="]" - echo "{\"status\":\"ok\",\"directory\":\"$TARGET_DIR\",\"hash\":\"$HASH_ALGO\",\"new\":$new_json,\"modified\":$mod_json,\"deleted\":$del_json}" + total_changes=$((${#new_files[@]} + ${#modified_files[@]} + ${#delete_files[@]})) + echo "{\"status\":\"ok\",\"directory\":\"$TARGET_DIR\",\"hash\":\"$HASH_ALGO\",\"files_scanned\":$file_count,\"total_changes\":$total_changes,\"new\":$new_json,\"modified\":$mod_json,\"deleted\":$del_json}" ;; csv)