[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-bash] Replace empty files with real ones
From: |
Greg Wooledge |
Subject: |
Re: [Help-bash] Replace empty files with real ones |
Date: |
Mon, 13 May 2019 08:53:15 -0400 |
User-agent: |
Mutt/1.10.1 (2018-07-13) |
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.