LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   A script to copy files. (https://www.linuxquestions.org/questions/linux-newbie-8/a-script-to-copy-files-846857/)

stf92 11-27-2010 05:01 AM

A script to copy files.
 
Hi:
Could you give me a script for copying all the files in a directory that are not directories to another directory. May be this could work:
Code:

FILE=(ls -l|grep ^-)
for i in $FILE
do
        cp $i /destination/path/$FILE
done

Thanks for reading.

druuna 11-27-2010 05:52 AM

Hi,

Would this helps: find . -maxdepth 1 -type f -exec cp {} /destination/path/{} \;

The above will look in the current directory (the . [dot]) for "normal" files (-type f) and copy them to /destination/path/.
The -maxdepth 1 option tells find to only look in the current directory.

Hope this helps.

rikijpn 11-27-2010 01:14 PM

what's wrong with the regular
Code:

cp * directory_target/
...?
it just outputs an "ommiting directory $dirname" string when source is a directory, but you can just redirect that to /dev/null like:
Code:

cp * directory_name 2>/dev/null
I don't see why such "over-coding" is necessary.

druuna 11-27-2010 01:42 PM

Hi,

@rikijpn: You are correct if you change that to: cp .* * /destination/path/
The .* needs to be included to also take care of all the dot files. And that is indeed the simplest way to do it.

Maybe the OP has a specific reason (exploring different ways to do things or getting some other inside?) for asking a script/one-liner.

stf92 11-27-2010 06:16 PM

The reason of using a loop instead of a single command is the loop would be just a skeleton to later fill with the appropriate stuff. So the question remains open: what corrections are necessary to make my script work? Thanks to both of you.

druuna 11-28-2010 03:07 AM

Hi,

Code:

#!/bin/bash

find . -maxdepth 1 -type f | \
while read thisFile
do
  cp "${thisFile}" "/destination/path/${thisFile}"
done

The above keeps the loop intact (although it is not a for x in y do loop). The output of the find command is piped to the while loop and files found are copied one at the time to the destination directory.

Do mind the quoting in the cp line, without it files with spaces will cause an error.

Hope this helps.

stf92 12-05-2010 10:39 AM

Hi:

It hurts me deeply to have missed your post, so didactic (I _can_ say didactic, by the sheer fact of learning a lot by reading it). I specially liked that about the spaces. And of course the pipe. Regards.

P.S.: something weird is happening to my control panel. Some posts arrive at it but some do not.

druuna 12-05-2010 12:01 PM

Hi,
Quote:

Originally Posted by stf92 (Post 4181309)
It hurts me deeply to have missed your post, so didactic (I _can_ say didactic, by the sheer fact of learning a lot by reading it). I specially liked that about the spaces. And of course the pipe. Regards.

You're welcome :)

Quote:

P.S.: something weird is happening to my control panel. Some posts arrive at it but some do not.
I never use the control panel/LQ UserCP for tracking posts. I enabled the 'Instant email notification' (Edit options -> Messaging & Notification -> Default Thread Subscription Mode).

grail 12-05-2010 06:17 PM

Also be aware that when using the piped method shown that any variables set / changed inside the loop will have all changes lost once leaving the loop.
Code:

#!/bin/bash

x=0

find . -maxdepth 1 -type f | \
while read thisFile
do
  cp "${thisFile}" "/destination/path/${thisFile}"
  ((x++))
done

echo "Number of copied files is $x"

This test will show that x still equals 0 after the loop.

stf92 12-06-2010 02:05 AM

And what makes the difference? I know of only one method of loosing those changes: a new instance of bash. So, this while runs in a new incarnation of bash?

grail 12-06-2010 02:37 AM

The pipe forces a subshell, hence it is like calling a bash script from a bash script and the outer has no knowledge of what the inner has done.

It is not really all that dramatic to solve, merely it comes dow3n to how the loop gets its information, like so:
Code:

#!/bin/bash

x=0

while read thisFile
do
  cp "${thisFile}" "/destination/path/${thisFile}"
  ((x++))
done< <(find . -maxdepth 1 -type f)

echo "Number of copied files is $x"

This simple change will now yield the correct results as the loop is now part of the original script.

stf92 12-06-2010 04:25 AM

Quote:

Originally Posted by grail (Post 4181974)
This simple change will now yield the correct results as the loop is now part of the original script.

That reasoning seems plausible (and a satisfying statement) to me. There being so much didactic material on shell scripting I'm beginning to feel a bit ashamed at making such elementary questions. Regards.

grail 12-06-2010 04:39 AM

Quote:

I'm beginning to feel a bit ashamed at making such elementary questions.
You should never feel ashamed. We all start somewhere. I like so many others are just happy to see people make an effort once supplied with information :)

stf92 12-06-2010 05:09 AM

Happy am I too to see you guys happy. And I'm now ready to mark SOLVED.
It is a sign of courtesy, I've been told, to make public a solution once found. No really _a_ solution, but the kind of solution I was seeking. So here it is:
Code:

#!/usr/bin/bash

# It has been tested.
LIST="$(ls u*.sh)"

for i in "$LIST" ; do
      echo "$i"
done
exit

The loop inner line is merely a placeholder here. Maybe I could use a while instead of the for. When I find how, I'll post it.

Note: if I had a file named "uma turman" in dir from where I run the script, that file would be listed too.

grail 12-06-2010 05:30 AM

May I suggest you perform the following change and check the output:
Code:

echo "|$i|"
They can be any symbol but the result might surprise you.


All times are GMT -5. The time now is 02:43 PM.