Unix cp argument list too long - unix

I am using AIX.
When I try to copy all the file in a folder to another folder with the following command:
cp ./00012524/*.PDF ./dummy01
The shell complains:
ksh: /usr/bin/cp: 0403-027 The parameter list is too long.
How to deal with it? My folder contain 8xxxx files, how can I copy them very fast? each file have size of 4x kb to 1xx kb.

Use find command in *nix:
find ./00012524 -type f -name "*.PDF" -exec cp {} ./dummy01/ \; -print

The cp command has a limitation of files which you can copy simultaneous.
One possibility you can copy them using multiple times the cp command bases on your file patterns, like:
cp ./00012524/A*.PDF ./dummy01
cp ./00012524/B*.PDF ./dummy01
cp ./00012524/C*.PDF ./dummy01
...
cp ./00012524/*.PDF ./dummy01
You can also copy trough find command:
find ./00012524 -name "*.PDF" -exec cp {} ./dummy01/ \;

$ ( cd 00012524; ls | grep '\.PDF$' | xargs -I{} cp {} ../dummy01/ )

The -t flag to cp is useful here:
find ./00012524 -name \*.PDF -print | xargs cp -t ./dummy01

The best command to copy large number of files from one directory to another.
find /path/to/source/ -name "*" -exec cp -ruf "{}" /path/to/destination/ \;
This helped me a lot.

You should be able use a for loop, e.g.
for f in $(ls ./00012524/*.pdf)
do
cp $f ./dummy01
done
I have no way of testing this, but it should work in theory.

you can do something like this and grab each line of the directory
# you can use the -rv to check the status of the command verbose
for i in /from_dir/*; do cp -rv "$i" /to_dir/; done

Related

Unix: find files in every subdirectory named upd

I have directory tree structure which looks like this
/app/bad/upd /app/pass/upd /app/bad/upd /app/warn/upd
I want to build a find command which can list all the files in every sub-directory named upd.
Currently I list it individually
find /app/bad/upd -type f -name "*${FILE_NAME}*"
This might be what you look for:
find /app -type d -name upd -exec ls -l {} +
or perhaps:
find /tmp/* -type d -name upd -exec sh -c "ls -l {}/*${FILE_NAME}* 2>/dev/null" sh {} \;
If the upd directory is always in the 2nd directory down, you could simply do:
ls /app/*/upd

Move only directories and not files in Unix OS

I had a directory with many files and sub-directories. To move only the sub-directories, I just learned you can use:
ls -d BASEDIR/*/ | xargs -n1 -I% mv % TARGETDIR/
I use the following:
$ mv ./*/ DirToMoveTo
For example:
Say I wanted to move all directories with "Old" in the name to a folder called "Old_Dirs" on /data.
The command would look like this:
mv ./*Old*/ /data/
Why not use find?
find . -maxdepth 1 -type d -exec mv '{}' /tmp \;
-maxdepth 1 makes sure find won't go deeper than current directory
-type d tells find to only find directories
-exec execute a command with the result of the find referenced by {}
In my opinion a cleaner solution and it also works better then using xargs when you have files with white space or tabs in them.
With a file structure like this:
/dir2move2
/dir
/subdir1
/subdir2
index.js
To move only the sub directories and not the files you could just do:
mv ./dir/*/ ./dir2move2
Possible solution:
find BASEDIR/ -maxdepth 1 -mindepth 1 -type d -exec mv '{}' TARGETDIR \;
you can simply use the same command for moving a file but put a slash after the name of the subdirectory
sudo mv */ path/to/destination
sudo mv subdir/ path/to/subdirectory

unix command to copy multiple files from different directories to one new directory

I am newbie to unix command usage.
I would like to ask if there is a way to copy multiple files from multiple directories into 1 new directory?
example:
in /tmp/dirA --> it contains file A.run.log and A.skip.log
in /tmp/dirB--> it contains file B.run.log and B.skip.log
in /tmp/dirC --> it contains file C.run.log and C.skip.log
and i would like to have all
A.run.log
A.skip.log
B.run.log
B.skip.log
C.run.log
C.skip.log
into a new folder called /tmp/dirNew
Is there a unix command that able to do it? Really appreciate it. Thank you.
JS
use this :
cp /tmp/dir?/* /tmp/dirNew
find /tmp -path "/tmp/dirNew" -prune -o -name '*.run.log' -exec cp {} /tmp/dirNew/ \;
find /tmp -path "/tmp/dirNew" -prune -o -name '*.skip.log' -exec cp {} /tmp/dirNew/ \;

How to move or copy files listed by 'find' command in unix?

I have a list of certain files that I see using the command below, but how can I copy those files listed into another folder, say ~/test?
find . -mtime 1 -exec du -hc {} +
Adding to Eric Jablow's answer, here is a possible solution (it worked for me - linux mint 14 /nadia)
find /path/to/search/ -type f -name "glob-to-find-files" | xargs cp -t /target/path/
You can refer to "How can I use xargs to copy files that have spaces and quotes in their names?" as well.
Actually, you can process the find command output in a copy command in two ways:
If the find command's output doesn't contain any space, i.e if the filename doesn't contain a space in it, then you can use:
Syntax:
find <Path> <Conditions> | xargs cp -t <copy file path>
Example:
find -mtime -1 -type f | xargs cp -t inner/
But our production data files might contain spaces, so most of time this command is effective:
Syntax:
find <path> <condition> -exec cp '{}' <copy path> \;
Example
find -mtime -1 -type f -exec cp '{}' inner/ \;
In the second example, the last part, the semi-colon is also considered as part of the find command, and should be escaped before pressing Enter. Otherwise you will get an error something like:
find: missing argument to `-exec'
find /PATH/TO/YOUR/FILES -name NAME.EXT -exec cp -rfp {} /DST_DIR \;
If you're using GNU find,
find . -mtime 1 -exec cp -t ~/test/ {} +
This works as well as piping the output into xargs while avoiding the pitfalls of doing so (it handles embedded spaces and newlines without having to use find ... -print0 | xargs -0 ...).
This is the best way for me:
cat filename.tsv |
while read FILENAME
do
sudo find /PATH_FROM/ -name "$FILENAME" -maxdepth 4 -exec cp '{}' /PATH_TO/ \; ;
done

Why doesn't my 'find' work like I expect using -exec?

I'm trying to remove all the .svn directories from a working directory.
I thought I would just use find and rm like this:
find . -iname .svn -exec 'rm -rf {}' \;
But the result is:
find: rm -rf ./src/.svn: No such file or directory
Obviously the file exists, or find wouldn't find it... What am I missing?
You shouldn't put the rm -rf {} in single quotes.
As you've quoted it the shell is treating all of the arguments to -exec it as a command rather than a command plus arguments, so it's looking for a file called "rm -rf ./src/.svn" and not finding it.
Try:
find . -iname .svn -exec rm -rf {} \;
Just by-the-bye, you should probably get out of the habit of using -exec for things that can be done to multiple files at once. For instance, I would write that out of habit as
find . -iname .svn -print | xargs rm -rf
or, since I'm now using a Macintosh and more likely to encounter file or directory names with spaces in them
find . -iname .svn -print0 | xargs -0 rm -rf
"xargs" makes sure that "rm" is invoked only once every "N" files, where "N" is usually 20. That's not a huge win in this case, because rm is small, but if the program you wanted to execute on every file was large or did a lot of processing on start up, it could make things a lot faster.
maybe its just me, but the old find & rm script does not work on my current config, a la:
find /data/bin/test -type d -mtime +10 -name "[0-9]*" -exec rm -rf {} \;
whereas the xargs solution does, a la:
find /data/bin/test -type d -mtime +10 -name '[0-9]*' -print | xargs rm -rf ;
no idea why, but i've updated my scriptLib so i dont spend another couple hours beating
my head on something so simple....
(running RHEL under kernel-2.6.18-194.11.3.el5)
EDIT: found out why - my RHEL distro defaults vi to insert the dreaded cr into line breaks (whch breaks the command) - following suggestions from nx5000 & jliagre at linuxquestions.org, added the following to ~/.vimrc:
:set fileformat=unix
map <F4> :set fileformat=unix<CR>
map <F5> :set fileformat=dos<CR>
which allows the behavior to pivot on the F4/F5.
to check whether CR's are embedded in your file:
head -1 scriptFile.sh | od -c | head -1
http://www.linuxquestions.org/questions/linux-general-1/bad-interpreter-no-such-file-or-directory-213617/
You can also use the svn command as follows:
svn export <url-to-repo> <dest-path>
Look here for more info.
Try
find . -iname .svn -exec rm -rf {} \;
and that probably ought to work IIRC.
You can pass anything you want in quotes, with the following trick.
find . -iname .svn -exec bash -c 'rm -rf {}' \;
The exec option will be happy to see that you're simply calling an executable with an argument, but your argument will be able to contain a script of basically any size and shape.
find . -iname .svn -exec bash -c '
ls -l "{}" | wc -l
' \;

Resources