help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] Replace empty files with real one


From: James
Subject: Re: [Help-bash] Replace empty files with real one
Date: Mon, 13 May 2019 15:51:50 +0200
User-agent: NeoMutt/20180716

First of all thank you for your answer!
I'm sorry for not being any clearer. I just thought I provided enough 
information.

What I was trying to say is they are all jpeg images files (either *.jpg or 
*.JPG).
All backups should be perfectly identical. There's no need to choose between 
the files,
anything with the same file name is fine. (it can't be any worse after all)
Only the base name matters.
All these (non-empty) images can be found in subdirectories under ~/Pictures.
(There are often many layers of subdirectories)
Currently the empty files are also in Picture (~/Picture/recovered) directory,
but I can separate them to make things easier. It's not a problem at all.
The sources (recovered files and backup files) have very different file 
hierarchy.
Their paths are so different.

Here's a real world example:
$ find ~/Pictures/recovered -type f -empty
        ./images/2012/06/12/DSC04506.JPG

$ find ~/Pictures -iname 'DSC04506*' -type f
        ./Pictures/Camera/Images/2012/DSC04506.JPG
        ./Pictures/Root/bckp/DSC04506_1.JPG
        ./images/2012/06/12/DSC04506.JPG

both DSC04506.JPG and DSC04506_1.JPG have the same checksums.

Thank you so much for your help!

On Sat, May 11, 2019 at 12:44:15AM +0200, James wrote:
> I'm in a nasty situation and I couldn't figure out how to solve this issue.
> A large number of my pictures are gone due to a badly written bash script.
> I could recover many of them but some are just empty files (with proper 
> names, though).
> Luckily, some pictures had been saved multiple places, and they had unique 
> file names.
> I was wondering if I could replace the empty files with regular images if 
> they have the very same file name?
> 
> For instance /mnt/recover/dir1/img007.jpg  file is empty but
> /home/user/Images/dir7/img007.jpg has content.
> (there can be many duplicates of img007.jpg elsewhere)
> 
> find /mnt/recover -type f -empty   found 20.000 files or so.

Where are these "multiple places" that the images can live?

When you say there "can be many duplicates of img007.jpg", does that mean
they're all identical files and you can choose any one of them from
among the non-empty files in the "multiple places"?  Or do you somehow
need to pick the "right one"?  How would that be determined -- timestamps?

I'm going to have to make some assumptions here.  It would be better if
things were spelled out explicitly.

Let's assume that you have:

1) One directory with empty files, all of which end in .jpg.  Using a
   recursive/hierarchical structure.

2) Three directories with non-empty files.  If a non-empty .jpg file
   found in any of these directories matches the name of an empty file
   in the first directory, copy it over the empty file.  Doesn't matter
   which non-empty file is used as long as the name matches.

So, here's the approach I would take:

1) Iterate over each of the three non-empty-file directories.  Store
   the pathnames of each .jpg file in an associative array indexed by
   the base filename.  E.g. file[img007.jpg]=/home/user/Images/dir7/img007.jpg

2) Once that array is populated, iterate over the directory with the empty
   files.  For each empty .jpg file, if an entry exists in the array, copy
   that pathname over the empty file.

Thus:

#!/bin/bash

dirs=(/home/user/Images /dir2 /another/directory)
empty=/mnt/recover
declare -A file

for d in "address@hidden"; do
  while IFS= read -rd '' f; do
    base="${f##*/}"
    file["$base"]="$f"
  done < <(find "$d" -type f -name '*.jpg' -print0)
done

while IFS= read -rd '' f; do
  base="${f##*/}"
  if [[ "${file["$base"]}" ]]; then
    printf 'copy <%s> <%s>\n' "${file["$base"]}" "$f"  # Comment me out later.
    # cp "${file["$base"]}" "$f"    # Uncomment me when you're sure it's safe.
  fi
done < <(find "$empty" -type f -name '*.jpg' -size 0 -print0)


This is untested, hence the printf instead of the live cp command.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]