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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .