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
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"