-1

I need to recursively go through a directory and all subdirectories and copy all files in them to an othet empty directory. "From" is the directory i want to go through and copy all files to "to". Currently it just copies all files from "from" to "to" and doesn't go in the subdirectories. Is there any way this will work or maybe some other way of doing this?

#/bin/bash
from=$1
to=$2
list=`ls -lR $from | grep '^-' | awk '{ print $10; }'`
for i in $list
do
cp $from/$i $to/$i
done 
Upe
  • 51
  • 1
  • 2
  • 6
  • 2
    `cp -r "$from" "$to"`? [Do no parse ls](https://unix.stackexchange.com/questions/128985/why-not-parse-ls-and-what-to-do-instead). [When to use quotes](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-round-a-shell-variable). Backticks \` are [strongly discouraged, use $(...) instead](https://wiki-dev.bash-hackers.org/scripting/obsolete) – KamilCuk Jan 09 '20 at 13:24
  • This works but it copies the directory and the subdirectories with files. I am trying to copy only the files. EX: a -a.txt -a1 --a1.txt I would like to copy only a1.txt and a.txt, without directories. – Upe Jan 09 '20 at 13:38
  • You mean that `./from/a//b/c/d/1.txt` should be copied to `./to/1.txt`? Please post a example directory structure before the operation and after the operation that you want to do, for example in the format similar to the output of `find`. – KamilCuk Jan 09 '20 at 13:38
  • And indent your code properly, for you (you will makes mistakes) and for us (not readable). – Gilles Quénot Jan 09 '20 at 13:39
  • Yes. Like only to copy the files that end on .txt. The directory i want to copy to should only have .txt files. – Upe Jan 09 '20 at 13:40

1 Answers1

1

You can use https://www.shellcheck.net/ to check your syntax, and learn about indentation. It will suggest some modifications to your code. Excellent suggestions also by @KamilCuk in the comments.

When you need to do something recursively in sub-directories, you can always use find with option -exec. You use {} to specify that the command should be applied to each file (or directory) that matches your find options.

This would do the trick: find $from -type f -name "*.txt" -exec cp {} $to \; -print

  • -type f: find all files
  • -exec cp {} $to \;: for each file that is found ({}), copy it to the $to directory. \; delimits the end of the command for option -exec.
  • -name "*.txt": if you want to filter by file name (here the extension .txt must be present to match).
  • -print: if you want to see which files are copied, as it goes through your directories.

Note also that find will work even if you have a huge number of sub-directories, or a very large number of files in them. ls sometimes fails, or takes an enormously long time to output large number of files.

Nic3500
  • 8,144
  • 10
  • 29
  • 40