LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   Assistance with 'find -exec cp' shell script (https://www.linuxquestions.org/questions/linux-software-2/assistance-with-find-exec-cp-shell-script-401653/)

dick.swift 01-10-2006 11:33 AM

Assistance with 'find -exec cp' shell script
 
Hello:

I have a script that I use to aide in data recovery when the host OS will not boot. Booting with a linux liveCD I execute a script with commands similar to:

Code:

find "$drive" -type f -name "*.pst" -exec cp {} /mnt/appcd/"$name" --parents --no-dereference \;
I'd like to add a little "prettiness" to it and allow for a verbose output, but only for the file being copied (not the entire command as '-v' offers) and also to show this only on one line (i.e. show the file being copied on one line, when the copy is complete remove the output from the first find/copy and show the next file being copied on the same line (replace the verbose output with each successive file)).

Is this possible?

Thanks in advance for any assistance

Dtsazza 01-10-2006 11:47 AM

My first thought is to take the verbose output from cp, and then trim it for prettiness with something like awk.

Let's see... standard 'cp -v' output is
Code:

`srcfile' -> `destfile'
So we can use awk to extract just the file we want (in either srcfile or destfile flavours) then used sed to trim off the ticks, like so:
Code:

cp -v /mnt/appcd/"$name" --parents --no-dereference | awk '{print($1)}' | sed -e "s/[\`\']//g"
(getting the quotes right in all of that is going to be fun...) As for displaying them on the same line, I think (though I might be wrong, never really having looked into it) you need a library like ncurses for that. The standard UNIX console tools simply write to standard out, which AFAIK doesn't have any absolute positioning.

Of course, if I am wrong, I'll be very happy to hear about it and learn how to do it! ;)

dick.swift 01-11-2006 10:56 AM

That is in the right ball park, but the added code is only showing me the first level of the path rather than the actual file.

Here's my code with the suggested addition of awk and sed:

Code:

find "$drive" -type f -name "*.pst" -exec cp {} /mnt/appcd/"$name" -v --parents --no-dereference \; | awk '{print($1)}' | sed -e "s/[\`\']//g"
I find that I get the same printed output with or without the sed portion.

So it seems very close to what I'm looking to accomplish, but need it to show only the file that is being copied - I don't want to see the path as that will be documented in the output from due to the --parents switch.

Thanks for your help - again this is getting me closer.

Dtsazza 01-11-2006 11:43 AM

Ah, for only getting the file I believe there's a very handy tool called basename that will do exactly what you want. :) Unfortunately, it won't take output through a pipe so we can't just stick it on the end as you'd expect. We can either pass basically the entire script into it as an argument (which works) or use some scripting tool to cut off all characters up to and including the last non-escaped forward slash. I'm going to go with the former, since although it doesn't look quite as nice it works fine and doesn't require extra thinking ;)

As for the sed not doing anything, does your cp -v surround the file names in ticks/quotes? Mine did, which is why I sed-ed them away, but if yours doesn't that's fine too.

So now we're up to
Code:

find "$drive" -type f -name "*.pst" -exec basename $(cp {} /mnt/appcd/"$name" -v --parents --no-dereference | awk '{print($1)}' | sed -e "s/[\`\']//g")
I'm afraid I've still had no luck on the creative positioning of strings on a console window, it's beyond my current knowledge. Hopefully someone else can step in and educate us both.

Andrzej

dick.swift 01-11-2006 12:52 PM

Thanks for the quick reply.

I'll have a look at basename.

I wasn't familiar with SED (until now) hence my uninformed statement about SED doing nothing (it actually was, just wasn't noticing).

I did however, through some tweaking, feel I've reached a compromise.

Code:

find "$drive" -type f -name "*.pst" -exec cp {} /mnt/appcd/"$name" -v --parents --no-dereference \; | awk '{print $3}' | sed -e "s/['\`\]//g"
by substituting $1 with $3, I am at least getting a paired down path/$filename (with the single quotes removed by SED). This may suffice while I investigate baseline or similar alternate methods.

Thanks again for your help!

Dtsazza 01-11-2006 03:20 PM

I don't know if you missed it - but there was a subtle change in the code that means basename is being called. By using the shell's "execute expression" brackets around basically the whole of the exec command, you can tell the shell to evaluate that part first then pass it in to basename. Note the part immediately after the -exec: basename $(cp... and then the extra bracket to close it all off at the end.

It's very easy to overlook when you have to scroll the little window too.

Dtsazza 01-23-2006 10:00 AM

OK, I knew there was some way of controlling the display of characters to a console, and the answer is via tput.

There are (by the looks of it) many fancy things you can do with tput - but the following four should be enough for your application:
Code:

tput lines            # Returns the number of lines on the current console
tput cols              # Returns the number of columns (i.e. characters per line) on the current console
tput cup $row $col    # Places the cursor at line $row, column $col (the top line is 0, and the bottom is $(tput lines) - 1).
tput el                # Deletes from cursor to end of line

These are really funky commands, and reflect the current window, not just the underlying terminal program - try issuing 'tput cols', resizing your window and issuing it again... now that's impressive. Anyway, you can read in the row and columns at the start of your script, and then before issuing the echo command, use 'tput cup x y' dollowed by 'tput el' to clear your old text, then write the new text on the same line. For sanity checks in case someone resizes the window, you may want to update your rows and columns count periodically, depending on how important it is to have them up-to-date.

At this point I'd like to say that while I think these commands will work fine, I've only just come across the command and haven't looked into the weird and wacky errors that may arise from strange configurations and unexpected use. I'd definitely recommend you have a look around for tput HOWTOs and learn its abilities and limitations for yourself.

It's pretty tasty, though.

Edit: oh, and while man tput isn't that information, man 5 terminfo gives you a long list of capabilities that you can get/set/otherwise exploit with tput. Some of these are more device-dependent than others, YMMV. :)

HTH,
Andrzej


All times are GMT -5. The time now is 07:42 PM.