3

I need to create a code that will:

  1. Check for two arguments at the start minus the script name itself (i.e dar /mnt/sdb1 /root/testdir/testarc with $1 = /mnt/sdb1 and $2 = /root/testdir/testarc)
  2. Copy all files with a .doc, .pdf and .PDF file extension from the source directory sdb1 (and its sub directories) to the destination directory
  3. Use some type of cmp command (or perhaps diff?) to rename any files that may have the same name but different data during the copy process
  4. If there is a .PDF/.pdf file with the same data as a .doc file then the .PDF/.pdf file should not be copied, only the .doc version

So far I have managed 1 and 2. 3 and 4 have me stumped.

Ignore the for loop, it's useless.

Here's my source code:

#!/bin/bash
sourcePath=$1
destPath=$2
Filedoc="*.doc"
Filepdf="*.pdf"
FilePDF="*.PDF"

if [[ $# -ne 2 ]]; then
    echo "Usage ; dar doc_path archive_path"
    exit 1
fi

if [ ! -d sourcePath ]
    then echo Directory does not exist
fi

if [ ! -d destPath ]
    then mkdir -p $destPath
fi

for file in $(find "${sourcePath}" -type f -exec basename {} \; | sort | uniq -d); do
  num=1 
  fileName=$(echo "${file}" | cut -d '.' -f1)
  fileExtension=$(echo "${file}" | cut -d '.' -f2)
  dirName=$(dirname "${duplicate}")
  for duplicate in $(find "${sourcePath}" -name "${file}" | tail -n +2 ); do
    mv "${duplicate}" "${duplicate}${fileName}_${num}.${fileExtension}"
    echo "Renamed duplicate file ${duplicate} ${duplicate}_${num}.${fileExtension}"
    (( num = num + 1 ))
  done
done

for file in $(find "${sourcePath}" -name "*.pdf"); do
  fileName=$(echo "${file}" | cut -d '.' -f1)
  if $(find $(sourcePath) -name "${fileName}.doc" &>/dev/nulll; then
    echo "Sorry, a .doc file with that extension already exists, skipping copy"
    continue
  fi
done

find "${sourcePath}" -name "$Filedoc" -exec cp -r {} "${destPath}" \;
find "${sourcePath}" -name "$Filepdf" -exec cp -r {} "${destPath}" \;
find "${sourcePath}" -name "$FilePDF" -exec cp -r {} "${destPath}" \;
  • 1
    Why would you link to a screenshot of your code? Paste the actual code into your question... – jasonwryan Nov 8 '15 at 17:26
  • 2
    Welcome to U&L! Please include your source code as text, not as image. For the step 3 I would recommend you to use diff (manual page here man7.org/linux/man-pages/man1/diff.1.html) The 4th point however is somewhat quite more complex than just a simple Bash script can do. Doc files and PDF files are binaries, but in different formats, therefore, from a binary point of view they are always going to be different – dave_alcarin Nov 8 '15 at 17:26
  • Apologies, it's been ammended in the OP – James Dean Nov 8 '15 at 17:48
  • 1
    When are documents considered the same? Does formatting matter or should only the text be the same? In the latter case you would need to convert the pdf and doc files to text. There is a pdf2txt utility if I'm not mistaken. And maybe libreoffice can help with the doc files. You can use -iname instead of -name in the find commands to reduce the number of searches. And you can combine both in the same find command. But if the names can differ you risk having to diff a large number of files. Finally the variables used in your sample code are inconsistent. – Bram Nov 8 '15 at 18:09
  • Same data as in the same text inside them/byte size i'm guessing. The specification I got never really detailed what exactly would be the difference as for the 3rd issue (renaming names that have the same name but different data), will that be some sort of diff command and a for loop inside? How would I go about structuring that? I'm a noob in the truest sense of the word – James Dean Nov 8 '15 at 18:17
1

You could use rsync with the --backup option to automatically make backups of files that exist in the destination directory. Note: this will only keep one backup copy - if the src file is changed twice, you will only have the most recent previous version as backup (renamed to filename~ by default)

e.g. something like:

#! /bin/bash

src="$1"
dst="$2"

# comment out the next line when you are sure it does what you want.
# And then try it with a trial destination dir a few times before
# running it with your real destination.
dryrun="--dry-run"

rsync $dryrun -avu --stats --progress --backup "$src" --include '**.doc' \
--include '**.pdf' --include '**.PDF' --exclude '**' "$dst/"  

If you wanted more backup copies, you could use the --backup-dir option. e.g.

#! /bin/bash

src="$1"
dst="$2"

dryrun="--dry-run"

BD=$(date '+%Y%m%d-%H%M%S')

rsync $dryrun -avu --stats --progress --backup --backup-dir="./$BD/" "$src" \
    --include '**.doc' --include '**.pdf' --include '**.PDF' \
    --exclude '**' "$dst/"  
1
cmp_or_rename()
    if    ! cmp -- "$1" "${2?NEED TWO ARGS}"
    then  ln -- "$1" "${1%.*}$((i+=1))${1#"${1%.*}"}"
    fi

...that only makes a hardlink, and I'm kinda iffy on which is source and which is dest and also a little on why... but if "$1" and "$2" are not names of two readable, identical files then "$1" is hardlinked to $1 - last ..* + (i++) + last ..*, or ln will let you know why not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.