1

I have a task to copy all files from multiple directories with special names to a target directory.

So I build this directory to test my command. The test directory tree looks like:

.
├── dir1
│   └── file1
└── test

My intended command to mv all files from dir1 to test is:

find . -type d -name "*dir*" -exec mv {}/* test \;

Then I got:

mv: rename ./dir1/* to test/*: No such file or directory

I guess this is because in that extra -exec expression, the command didn't treat the * as a wildcard.

So I did:

find . -type d -name "*dir*" -exec mv {}/file1 test \;

Which successfully moved file1 to test.

But the point is, I need to now the expression for all files so that I can accomplish this file transfer work.

How should I express that in the find -exec command group?

2

mv "$dir_path"/* ... will not only move files but everything in "$dir_path". At least everything whose name does not start with a dot (hidden files). In bash you can change this with the option dotglob. But if the * expands nicely (matches everything but not too much for a command line) then you can use a shell for indirection:

find . -type d -name "*dir*" -exec bash -c 'mv "$0"/* /path/to/test' {} \;
  • what does the end \; mean? Can them be omitted? I'm been have this doubt for a long time. – Zen Jan 16 '15 at 9:13
  • The ; is the end of the -exec block (other tests / commands may follow). But as it is also a shell control operator it must be quoted for becoming part of the command line. You could use ';' or ";". – Hauke Laging Jan 16 '15 at 9:22
  • 1
    Don't interpolate {} inside a shell script. That can't work unless you know that the file names are restricted to a “tame” set of characters. When you use {} inside a shell snippet, the file name is interpreted as a piece of shell syntax instead of being correctly treated as a string. Pass the file name as an argument instead. Cc @Zen – Gilles Jan 16 '15 at 22:45
2

Try:

$ find -type d -name '*dir*' -exec sh -c '
  for d do
    for f in "$d"/*; do
      [ -f "$f" ] && mv -- "$f" /path/to/test
    done
  done
' sh {} +
  • Have you tried that? I guess -exec doesn't allow arguments between {} and +. You need mv -t /path/to/test -- {} +. – Hauke Laging Jan 16 '15 at 4:54
  • @HaukeLaging: Oh, my bad, It had another error that only one instance of {} is allowed. I changed my solution. – cuonglm Jan 16 '15 at 5:54
  • This is too complicate. – Zen Jan 16 '15 at 9:22
  • @Zen: Yes, the extra work to copy files only. – cuonglm Jan 16 '15 at 9:25
0

You might try this as well . Considering the test directory is in the same directory with other directories ,

find . -mindepth 2  ! -name test -exec cp {} test \;

This will copy all individual files to the directory test , escaping the dir1 , dir2 etc. Note that this will omit subdirectories itself and copies contents of them. you can also test this by using ls command.

find . -mindepth 2  ! -name test -ls 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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