I already tried to find answer here, but didn't find. I am sorry my bad english, because it is a bit hard for me to speak english. I also have almost none bash scripting skills, so my script may look very bad. It's jus made from examples what I could find from internet, but now I am against wall with this, so I need help from you guys!

What I need from this script is:

  1. Find all pdf files recursively (Simple Machines Forum hashes attachments, so that is why extension is .dat)
  2. Identify pdf type from .dat files
  3. Then I need to use ps2pdf program to optimize all new (last 24h) pdf files
  4. I also need to keep original timestamp from optimized pdf files
  5. That "24h-pdf-compress-"date +"%d-%m-%Y"".txt" file is only for logging things, so I can check later it is working.

Smf- forum attachments dir structure is following:

Under attachment folder there is folder by year (2020).
Under every year there is folder for month (04 = April).
Under every month are the all attachment files from that month.
Every file (jpg,png,pdf) have the same .dat extension.


My script:


cd /var/www/foorumi/attachments

find . -name '*.dat' -mtime -1 | xargs file -i | grep 'pdf' | cut -d: -f1 > "24h-pdf-compress-"`date +"%d-%m-%Y"`".txt"
find . -name '*.dat' -mtime -1 | xargs file -i | grep 'pdf' | cut -d: -f1 | while read -r file

        touch -r "$file" "dummy_file"
        ps2pdf "$file" "new_$file" # PROBLEM
        rm "$file"
        mv "new_$file" "$file" # PROBLEM
        touch -r "dummy_file" "$file"
        rm dummy_file

mv "24h-pdf-compress-"`date +"%d-%m-%Y"`".txt" /root/24h_pdf_compress_log
find . -iname '*.dat' -user root -exec chown www-data:www-data {} \;

exit 0

Ok, problem is following. When I run find . -name '*.dat' -mtime -1 | xargs file -i | grep 'pdf' | cut -d: -f1 it prints files like ./04/somepdfattachment.dat, so when script runs ps2pdf "$file" "new_$file" it tries to make new file name like new_./04/somepdfattachment.dat..it doesn't sound right.

Next error comes when script tries to rename file mv "new_$file" "$file", because now it tries to rename new_./04/somepdfattachment.dat file back it's original filename.

I hope you understand what I try to tell you. I can provide more info if needed.

Thanks in advance!

UPDATE! Like @pLumo suggested, I modified script and it seems to work now. I hope I understood suggestions correctly..

Simple Machines forum attachments are named following way: 403_57066cef00fb1d57137b5613f076d254e89b88bc.dat
"403" = are running number for attachments, next is 404 and next 405 and so on..
"57066cef00..." = is random hash
".dat"= all attachments extensions (jpg,png,pdf) are renamed as .dat after upload.

Updated script:

        touch -r "$file" "dummy_file"
        newname="$(dirname "$file")/new_$(basename "$file")"
        ps2pdf "$file" "$newname" || continue
        rm "$file"
        mv "$newname" "$file"
        touch -r "dummy_file" "$file"
        rm dummy_file
  • To start with, this is why it's not a good idea to parse the output of find. Are all of the files in /var/www/foorumi/attachments/2020/04/? If so cd into it and then use printf '%s\n' * to return the filenames without the directory appended. Also, add the expected output to your question so that there is a better idea of what you are trying to do. Apr 2, 2020 at 6:14
  • @Nasir Riley no need for printf, file reads multiple files directly: file -i0 *. btw, find, unlike ls can be used safely.
    – pLumo
    Apr 2, 2020 at 7:08
  • It isn't a good idea to parse the output find, either: unix.stackexchange.com/questions/321697/… Using find -exec is okay, but not for what HendriXXX is trying to do. Apr 2, 2020 at 7:35
  • To be precise: parsing find done right is totally fine, but you may be talking (and linked) looping.
    – pLumo
    Apr 2, 2020 at 8:02

1 Answer 1


You need to split $file into its path (dirname) and filename (basename) and put the new_ in between:

newname="$(dirname "$file")/new_$(basename "$file")"
ps2pdf "$file" "$newname"

Additional hints:

  • your find command is not safe when you have newlines in the results it will screw up your results. You might want to get yourself familiar with the zero-delimiter to pipe file names safely.
  • I think the same applies if you have colons in the filenames, your cut will split at the wrong place.
  • Use -exec instead of xargs: find . -name '*.dat' -mtime -1 -exec file -i {} +
  • If ps2pdf fails you are still going on, deleting the original file. You can use for example: ps2pdf ... || continue to jump to the next iteration on failure.
  • Please use a more descriptive title, then your Q may help other people too.

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.