1. Detectar el problema
En la herramienta "disks" de Ubuntu me dice:
s'ha produit un error en muntar el sistema de fitxers Error mounting /dev/sdc4 at /media/eduard/22143F41143F176F;wrong fs type, bad option, bad superblock on /dev/sdc4, missing codepage or helper program, or other error (udisks-error-quark,0)
Por tanto el problema es en el disco /dev/sdc4
2. Detectar el tipo de partición
Ejecutamos:
sudo fdisk -l
Y vemos que es NTFS (que también se podía ver en la herramienta "Disks" de ubuntu
3. Probar a montar manualmente
Ejecutamos:
sudo mount -t ntfs /dev/sdc4 /mnt
y responde:
$MFTMirr does not match $MFT (record 3). Failed to mount '/dev/sdc4': Error d’Entrada/Sortida NTFS is either inconsistent, or there is a hardware fault, or it's a SoftRAID/FakeRAID hardware. In the first case run chkdsk /f on Windows then reboot into Windows twice. The usage of the /f parameter is very important! If the device is a SoftRAID/FakeRAID then first activate it and mount a different device under the /dev/mapper/ directory, (e.g. /dev/mapper/nvidia_eahaabcc1). Please see the 'dmraid' documentation for more details.
4. Instalar software adicional y utilizarlo
sudo apt install ntfs-3g
sudo ntfsfix /dev/sdc4
y contesta:
Mounting volume... Windows is hibernated, refused to mount. FAILED Attempting to correct errors... Processing $MFT and $MFTMirr... Reading $MFT... OK Reading $MFTMirr... OK Comparing $MFTMirr to $MFT... OK Processing of $MFT and $MFTMirr completed successfully. Setting required flags on partition... OK Going to empty the journal ($LogFile)... OK Windows is hibernated, refused to mount. Remount failed: Operation not permitted
cosa que dice que windows está "hibernated" y se debe a que se interrumpioun proceso de E/AS en el disco y que no se debe acceder a el para modificar nada si no se opera desde windows.
Por tanto lo que podemos hacer es montarlo de solo lectura y copiar los datos
4. Montar el disco de solo lectura
sudo mount -t ntfs-3g -o ro /dev/sdc4 /mnt
y ya podemos acceder a el disco o la partición en el directorio /mnt
5. Copia de seguridad multifichero
Se opta por copiar a otro disco mas grande y luego crear un zip multivolumen de ficheros de 4 gigas con:
cd /home/eduard
zip -r -s 4g MIS_DATOS.zip MIS_DATOS
donde la carpeta que contiene los datos a guradar es /home/eduard/MIS_DATOS
y esto genera estos ficheros:
MIS_DATOS.z01, MIS_DATOS.z02, ....MIS_DATOS.88, MIS_DATOS.zip
Siendo MIS_DATOS.88 en mi caso el penúltimo fichero y MIS_DATOS.zip el último
Para descomprimir utilizar:
unzip MIS_DATOS.zip
asegurándose que todos los ficheros generados esten disponibles en la misma carpeta.
Si solo se quiere extraer una subcarpeta llamada MI_SUBCARPETA se haría_
unzip MIS_DATOS.zip "MIS_DATOS/MI_SUBCARPETA/*" -d /ruta/de/destino
y si solo queremos listar el contenido:
unzip -l MIS_DATOS.zip | less
6. Ver si hay muchos duplicados. Borrado y copia sin duplicados
Con chatgpt he creado un bash para detectar duplicados y en su caso borrarlos. Pero en el siguiente punto se ha hecho un bash que solo copia los ficheros no duplicados.
El fichero a no borrar de los duplicados es aquel que tiene menor numero de anidamientos en carpeta.
Ver y/o eliminar duplicados (buscar_duplicados_carpeta.sh)
#!/bin/bash # buscar_duplicados.sh # Busca y (opcionalmente) elimina ficheros duplicados (por nombre y tamaño) # e informa del espacio total y del potencial ahorro. # Uso: # ./buscar_duplicados.sh /ruta/a/carpeta [eliminar_duplicados] BASE_DIR="$1" ACCION="$2" # --- Validaciones iniciales if [[ -z "$BASE_DIR" ]]; then echo "❌ Uso: $0 /ruta/a/carpeta [eliminar_duplicados]" exit 1 fi if [[ ! -d "$BASE_DIR" ]]; then echo "❌ No existe el directorio: $BASE_DIR" exit 1 fi # --- Variables REPORT_FILE="duplicados_$(date +%Y%m%d_%H%M%S).txt" > "$REPORT_FILE" ELIMINAR=false if [[ "$ACCION" == "eliminar_duplicados" ]]; then ELIMINAR=true fi echo "🔍 Buscando duplicados en: $BASE_DIR" echo "📝 Informe: $REPORT_FILE" echo # --- Calcular espacio total de la carpeta (en bytes) TOTAL_BYTES=$(du -sb "$BASE_DIR" | awk '{print $1}') TOTAL_HUMAN=$(du -sh "$BASE_DIR" | awk '{print $1}') echo "💾 Espacio total actual ocupado por la carpeta: $TOTAL_HUMAN ($TOTAL_BYTES bytes)" echo "💾 Espacio total actual ocupado por la carpeta: $TOTAL_HUMAN ($TOTAL_BYTES bytes)" >> "$REPORT_FILE" echo # --- Buscar duplicados POTENCIAL_AHORRO=0 find "$BASE_DIR" -type f -printf '%s\t%p\n' | \ while IFS=$'\t' read -r SIZE FILE; do BASENAME=$(basename "$FILE") echo -e "$BASENAME\t$SIZE\t$FILE" done | sort -k1,1 -k2,2n | \ awk -F'\t' -v ELIMINAR="$ELIMINAR" -v REPORT_FILE="$REPORT_FILE" -v BASE_DIR="$BASE_DIR" ' function human(bytes) { hum[1024^4]="TB"; hum[1024^3]="GB"; hum[1024^2]="MB"; hum[1024]="KB"; for (x=1024^4; x>=1024; x/=1024) if (bytes>=x) return sprintf("%.2f %s", bytes/x, hum[x]); return bytes " B"; } { name=$1; size=$2; path=$3; key=name"|"size; files[key]=files[key]?files[key]"\n"path:path; sizes[key]=size; } END { total_savings=0; for (k in files) { split(files[k], arr, "\n"); if (length(arr) > 1) { print "📁 Duplicado: " k >> REPORT_FILE; print "📁 Duplicado: " k; # Calcular profundidad min=999999; minpath=""; for (i in arr) { split(arr[i], dirs, "/"); depth[i]=length(dirs); if (depth[i] < min) { min=depth[i]; minpath=arr[i]; } } print " ✅ Se conservará: " minpath >> REPORT_FILE; print " ✅ Se conservará: " minpath; print " ❌ Duplicados encontrados:" >> REPORT_FILE; for (i in arr) { if (arr[i] != minpath && arr[i] != "") { print " " arr[i] >> REPORT_FILE; print " " arr[i]; total_savings += sizes[k]; # sumamos el tamaño de los que se podrían eliminar } } if (ELIMINAR == "true") { printf "\n¿Eliminar todos los duplicados de este grupo (excepto el conservado)? (s/n): "; getline resp < "/dev/tty"; if (resp == "s" || resp == "S") { for (i in arr) { if (arr[i] != minpath && arr[i] != "") { cmd="rm -i \""arr[i]"\""; system(cmd); print " ➜ Eliminado: " arr[i] >> REPORT_FILE; } } } else { print " ➜ No se eliminaron duplicados de este grupo." >> REPORT_FILE; } } print "" >> REPORT_FILE; print ""; } } print "--------------------------------------------" >> REPORT_FILE; print "📊 Espacio total potencial a liberar: " human(total_savings) " (" total_savings " bytes)" >> REPORT_FILE; print "--------------------------------------------" >> REPORT_FILE; print "\n📊 Espacio total potencial a liberar: " human(total_savings) " (" total_savings " bytes)"; }' echo echo "✅ Proceso finalizado." echo "📄 Informe generado en: $(realpath "$REPORT_FILE")" # --- Calcular de nuevo el tamaño si se eliminaron duplicados if [[ "$ELIMINAR" == "true" ]]; then FINAL_BYTES=$(du -sb "$BASE_DIR" | awk '{print $1}') FINAL_HUMAN=$(du -sh "$BASE_DIR" | awk '{print $1}') echo echo "💾 Espacio tras eliminar duplicados: $FINAL_HUMAN ($FINAL_BYTES bytes)" echo "💾 Espacio tras eliminar duplicados: $FINAL_HUMAN ($FINAL_BYTES bytes)" >> "$REPORT_FILE" fi
copiar carpeta sin duplicados creando un fichero de duplicados dentro de la carpeta destino (copiar_carpeta_no_duplicados.sh)
#!/bin/bash # copiar_sin_duplicados.sh # Copia solo los ficheros no duplicados (por nombre y tamaño) # y genera informes de los archivos copiados y duplicados. echo "📁 Introduce la ruta de la carpeta origen:" read -r ORIGEN if [[ ! -d "$ORIGEN" ]]; then echo "❌ La carpeta origen no existe." exit 1 fi echo "📂 Introduce la ruta de la carpeta destino:" read -r DESTINO # Crear carpeta destino si no existe mkdir -p "$DESTINO" # Archivos temporales e informes TMP_FILE=$(mktemp) REPORT_FILE="copiados_$(date +%Y%m%d_%H%M%S).txt" DUPLICADOS_FILE="$DESTINO/duplicados_$(date +%Y%m%d_%H%M%S).txt" > "$REPORT_FILE" > "$DUPLICADOS_FILE" echo "🔍 Analizando duplicados en: $ORIGEN" echo # --- Calcular tamaño total de la carpeta origen TOTAL_BYTES=$(du -sb "$ORIGEN" | awk '{print $1}') TOTAL_HUMAN=$(du -sh "$ORIGEN" | awk '{print $1}') echo "💾 Tamaño total de la carpeta origen: $TOTAL_HUMAN ($TOTAL_BYTES bytes)" echo "💾 Tamaño total de la carpeta origen: $TOTAL_HUMAN ($TOTAL_BYTES bytes)" >> "$REPORT_FILE" echo >> "$REPORT_FILE" # --- Buscar duplicados (por nombre + tamaño) find "$ORIGEN" -type f -printf '%s\t%p\n' | \ while IFS=$'\t' read -r SIZE FILE; do BASENAME=$(basename "$FILE") echo -e "$BASENAME\t$SIZE\t$FILE" done | sort -k1,1 -k2,2n | \ awk -F'\t' -v TMP_FILE="$TMP_FILE" -v DUPLICADOS_FILE="$DUPLICADOS_FILE" ' { name=$1; size=$2; path=$3; key=name"|"size; files[key]=files[key]?files[key]"\n"path:path; sizes[key]=size; } END { for (k in files) { split(files[k], arr, "\n"); if (length(arr) > 1) { print "-----------------------------------" >> DUPLICADOS_FILE; print "Duplicado (" k "):" >> DUPLICADOS_FILE; for (i in arr) { print arr[i] >> TMP_FILE; print " " arr[i] >> DUPLICADOS_FILE; } } } }' # --- Copiar solo los no duplicados echo "🚀 Iniciando copia de ficheros no duplicados..." echo >> "$REPORT_FILE" echo "=============================" >> "$REPORT_FILE" echo "COPIA DE FICHEROS NO DUPLICADOS" >> "$REPORT_FILE" echo "=============================" >> "$REPORT_FILE" echo >> "$REPORT_FILE" COUNT=0 BYTES_TOTAL_COPIADOS=0 BYTES_DUPLICADOS=0 # Calcular espacio potencial de duplicados while IFS= read -r FILE_DUP; do if [[ -f "$FILE_DUP" ]]; then SIZE=$(stat -c%s "$FILE_DUP") BYTES_DUPLICADOS=$((BYTES_DUPLICADOS + SIZE)) fi done < "$TMP_FILE" # Copiar los no duplicados while IFS= read -r FILE; do # Saltar duplicados if grep -Fxq "$FILE" "$TMP_FILE"; then continue fi REL_PATH="${FILE#$ORIGEN/}" DEST_PATH="$DESTINO/$REL_PATH" DEST_DIR=$(dirname "$DEST_PATH") mkdir -p "$DEST_DIR" cp -p "$FILE" "$DEST_PATH" SIZE=$(stat -c%s "$FILE") BYTES_TOTAL_COPIADOS=$((BYTES_TOTAL_COPIADOS + SIZE)) COUNT=$((COUNT + 1)) echo "✔ Copiado: $DEST_PATH" >> "$REPORT_FILE" done < <(find "$ORIGEN" -type f) # --- Función para tamaños legibles function human_readable { local bytes=$1 local units=("B" "KB" "MB" "GB" "TB") local i=0 local value=$bytes while (( value >= 1024 && i < 4 )); do value=$(( value / 1024 )) ((i++)) done echo "${value} ${units[$i]}" } TOTAL_HUMAN_COPIADOS=$(human_readable "$BYTES_TOTAL_COPIADOS") TOTAL_HUMAN_DUPLICADOS=$(human_readable "$BYTES_DUPLICADOS") # --- Resultados finales echo echo "✅ Copia completada." echo "📊 Archivos copiados: $COUNT" echo "📦 Tamaño total origen: $TOTAL_HUMAN ($TOTAL_BYTES bytes)" echo "📥 Tamaño copiado (sin duplicados): $TOTAL_HUMAN_COPIADOS ($BYTES_TOTAL_COPIADOS bytes)" echo "💾 Espacio ahorrado (duplicados no copiados): $TOTAL_HUMAN_DUPLICADOS ($BYTES_DUPLICADOS bytes)" echo echo "📄 Informe de copiados: $(realpath "$REPORT_FILE")" echo "📁 Listado de duplicados: $(realpath "$DUPLICADOS_FILE")" echo >> "$REPORT_FILE" echo "-------------------------------------" >> "$REPORT_FILE" echo "📦 Tamaño total origen: $TOTAL_HUMAN ($TOTAL_BYTES bytes)" >> "$REPORT_FILE" echo "📥 Tamaño copiado (sin duplicados): $TOTAL_HUMAN_COPIADOS ($BYTES_TOTAL_COPIADOS bytes)" >> "$REPORT_FILE" echo "💾 Espacio ahorrado (duplicados no copiados): $TOTAL_HUMAN_DUPLICADOS ($BYTES_DUPLICADOS bytes)" >> "$REPORT_FILE" echo "-------------------------------------" >> "$REPORT_FILE" # --- Limpieza rm -f "$TMP_FILE"