Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

What I am attempting to do is combine all of the files within a subdirectory into a new file, and give the new combined file the same name as the subdirectory, and I have no idea how to do this in Bash. Here's how I approached it: I have a number of directories, each with a unique file name (with spaces!). Within each of these directories, there are a number of numerically named files, like thus:

Home/Unique name/1.pdf  
Home/Unique name/2.pdf  
Home/Unique name/3.pdf  
Home/Unique name/4.pdf  
....  
Home/Other Unique name/1.pdf  
Home/Other Unique name/2.pdf  
Home/Other Unique name/3.pdf  
Home/Other Unique name/4.pdf

What I would like to do is write a bash script (from the Home directory) to:

  1. Go into each unique directory, and perform a command on each of the files within that directory (in my case, copy them all to a different directory).
  2. I have then written a different script script.sh that will perform another command (in this case, combine all the PDFs into a single file, temp.pdf). I would then like to rename that temp.pdf file after the directory Unique name.pdf (with spaces).
  3. I will have to follow this process for a number of subdirectories.

I have attempted a solution with a number of for loops, while loops and using the find command, but I am not comfortable enough with bash to debug comfortably or use these variables with any degree of confidence. I am also certain that there is a more efficient way to do what I am doing, but I have bootstrapped the script together over a period of time.

share|improve this question
    
Should be a relatively simple C or Java program. –  Daniel R Hicks May 30 '13 at 11:40
    
Unless you're doing this for plain-text encoded files, the resulting files will not be considered valid. For example, if you just concatenate the binary data in a few PDFs, the resulting file is not a PDF-compliant file (if you're lucky, it might show you the first PDF only). You need a specific tool for the format of files you want to join. To join several files, however, you can just use cat to display them all in the proper order, and pipe the results of cat into a new file. –  Breakthrough May 30 '13 at 12:16
    
@DanielRHicks using C for something this simple would be hilariously overkill –  evilsoup May 30 '13 at 12:24
add comment

2 Answers

The POSIX way is to use print . -type d ... | while read f; do, but unless you're obsessed with 100% portability, I wouldn't bother with that. If you have bash 4+ and pdfunite (installed by default on my Ubuntu 13.04), you can do this in two lines:

shopt -s globstar
for f in ./**/; do pdfunite "$f"/*.pdf "$f"/"$(basename "$f").pdf"; done

Note that shopt -s globstar needs to be on a separate line to the rest of it. With globstar enabled, ** expands to all files and directories in the current directory, recursively. Since files cannot contain / in their names, **/ will expand to only the directories. I use ./**/ in the unlikely event that your directories begin with a hyphen (-), as this can cause problems, since many programs treat anything beginning with a - as an option.

As written, this will not copy the PDFs to another directory, but that's pretty trivial to add in:

for f in ./**/; do cp "$f"/*.pdf /target/dir/; pdfunite "$f"/*.pdf "$f"/"$(basename "$f").pdf"; done

If you want to use your own custom pdf-combining script, then simply change the line to suit - but remember that the essence of shell scripting is putting together pre-existing commands.

Here's a somewhat more portable version:

print . -type d -print0 | while read -d $'\0' f; do
  pdfunite "$f"/*.pdf "$f"/"$(basename "$f").pdf"
done
share|improve this answer
add comment
  1. Create for loop with find /home/ -type f -name "*.pdf" as a variable
  2. Copy files to where you need them to, take $VARIABLE and process it through sed/awk to remove "/".

Post your script and we can help you to improve it.

You can always run scripts with bash -x to debug them or you can set !#/bin/bash -x to always execute in debug (verbose) mode.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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