I'm still new to linux scripting, so this might be a bit trivial.
As part of my script, I am trying to copy all the modified files (relative to the original backup I have made) to another folder while keeping the file structure.
I have found this method:
find /SourceFolder/ -newer /BackupFOlder/ -exec cp --parents \{\} /Destination
However the above command does not work, giving me the error:
find: missing argument to 'exec'
Why doesn't this work?
I also found this:
Copy files preserving folder structure
But I want to use cp command only.
Would really appreciate some help.
The -exec option requires a ; argument to tell it where the command ends, because you could have additional find options after it.
find /SourceFolder/ -newer /BackupFOlder/ -exec cp --parents {} /Destination \;
However, a better solution would be to use rsync:
rsync -a /SourceFolder /BackupFolder
Try
tar cf - . | (cd <some other dir>; tar xfv -)
Related
I have a folder, which consists of many folders and many tar files. (this many is around 1000)
I want to write a script to copy all folders with their contents to another directory, but I do not want to copy tar files.
I already know by writing
cp -a /source/ /path/
I can copy a directory with its contents to another, but for this case, I do not know how to do it.
As the number of directories are alot, I am not able to each time copy one directory.
I appreciate if someone can help me on this.
I think this might be what you're looking for.
You want to use the rsync command and in the --exclude flag you want to put *.tar
So your answer will look something like this:
rsync -r --exclude='*.tar' [source] [destination]
This is also a helpful little tutorial on how to use rsync.
You can combine cp in find to exclude *.tar files:
dest='/path/'
mkdir "$dest" &&
find /source -mindepth 1 -not -name '*.tar' -exec cp -a {} "$dest" \;
I need to find all files in a directory and it's subdirectories, but I need to keep directory structure. For example there is a file
/media/subdir1/subdir2/file.jpg
and I want to copy it to
/new-media/subdir1/subdir2/file.jpg
and the same to all files inside /media/ directory. And by the way, directories inside /new-media/ must be created if not exist.
if I use
find /media/ -name '*.jpg' -exec cp /new-media/ ????? {} \;
how can I get all subdirectories inside /media/?
The above will get you everything in /media, but to get exactly what you want you probably want to use something like:
Method 1: Copy only what you need recursively, per your requirements:
mkdir ../media2; find . -name "*.jpg" -exec cp -r --parents {} ../media2 \;
I ran this from inside the directory you want to search recursively. It does a couple things:
1 - create the new destination directory
mkdir ../media2
2 - then finds all files ending with ".jpg" recursively.
find . -name "*.jpg"
3 - uses -exec to pass the copy command to each file returned to find as a match, and subs that in as the first argument (which with the syntax of cp, is going to be your source file):
-exec cp -r --parents {} ../media2 \;
the "--parents" flag retains existing directory structure and recursively creates subsequent parent directories. Super useful right?
Method 2: there might be a better way to do this with xargs, but the above ended up being the most simple method imho. That said, if you want to think outside the box, you could simply copy the entire directory over recursively, then remove anything NOT ending with ".jpg" with something like:
cp -r media media2; find ./media '!'-name "*.jpg" -type f | xargs rm
I think this is what you want:
cp -r /media /new-media
-R, -r, --recursive
copy directories recursively
Hope this helps.
I'm making a bash script that should backup all files and dir structure to another dir.
I made the following code to do that:
find . -type f -exec cp {} $HOME/$bdir \; -o -type d -exec mkdir -p {} $HOME/$bdir \; ;
The problem is, is that this only copies the files and not the dir structure.
NOTE: I may not use cp -r, cp -R or something like it because this code is part of an assignment.
I hope somebody can put me in the right direction. ;)
Joeri
EDIT:
I changed it to:
find . -type d -exec mkdir -p $HOME/$bdir/{} \; ;
find . -type f -exec cp {} $HOME/$bdir/{} \; ;
And it works! Ty guys ;)
This sounds like a job for rsync.
You mention that this is an assignment. What are your restrictions? Are you limited to only using find? Does it have to be a single command?
One way to do this is to do it in two find calls. The first call only looks for directories. When a directory is found, mkdir the corresponding directory in the destination hierarchy. The second find call would look for files, and would use a cp command like you currently have.
You can also take each filename, transform the path manually, and use that with the cp command. Here's an example of how to generate the destination filename:
> find . -type f | sed -e "s|^\./|/new/dir/|"
/new/dir/file1.txt
/new/dir/file2.txt
/new/dir/dir1/file1_1.txt
/new/dir/dir1/file1_2.txt
For your purposes, you could write a short bash script that take the source file as input, uses sed to generate the destination filename, and then passes those two paths to cp. The dirname command will return the directory portion of a filename, so mkdir -p $(dirname $destination_path) will ensure that the destination directory exists before you call cp. Armed with a script like that, you can simply have find execute the script for every file it finds.
cd olddir; tar c . | (cd newdir; tar xp)
Can you do your find with "-type d" and exec a "mkdir -p" first, followed by your find that copies the files rather than having it all in one command? It should probably also be mkdir -p $HOME/$bdir/{}.
I have a bunch of zip files, and I'm trying to make a bash script to automate the unzipping of certain files from it.
Things is, although I know the name of the file I want, I don't know the name of the folder it's in; it is one folder depth in
How can I extract these files, preferably discarding the folder?
Here's how to unzip any given file at any depth and junk the folder paths on the way out:
unzip -j somezip.zip *somefile.txt
The -j junks any folder structure in the zip file and the asterisk gives a wildcard to match along any path.
if you're in:
some_directory/
and the zip files are in any number of subdirectories, say:
some_directory/foo
find ./ -name myfile.zip -exec unzip {} -d /directory \;
Edit: As for the second part, removing the directory that contained the zip file I assume?
find ./ -name myfile.zip -exec unzip {} -d /directory \; -exec echo rm -rf `dirname {}` \;
Notice the "echo." That's a sanity check. I always echo first when executing something destructive like rm -rf in a loop/iterative sequence like this. Good luck!
Have you tried unzip somefile.zip "*/blah.txt"?
You can use find to find the file that you need to unzip, and xargs to call unzip:
find /path/to/root/ -name 'zipname.zip' -print0 | xargs -0 unzip
print0 enables the command to work with files or paths that have white space in them. -0 is the option to xargs that makes it work with print0.
I am trying to copy all jpgs from 1 directory to another but only new files and ones that have been updated.
I am using the following command:
\cp -uf /home/ftpuser1/public_html/ftparea/*.jpg /home/ftpuser2/public_html/ftparea/
And I am getting the error:
-bash: /bin/cp: Argument list too long
I am assuming that there are 2 many files in this directory for the cp command to work
I have also tried:
find /home/ftpuser1/public_html/ftparea/ -name "*jpg" -exec cp -uf {} /home/ftpuser2/public_html/ftparea/
and got the following:
find: missing argument to `-exec'
Any ideas?
You need to make sure to include the final “\;” to finish the command that -exec should execute.
Using find you shouldn't have the brackets in quotes. Try this
find /home/ftpuser1/public_html/ftparea/ -name "*jpg" -exec cp -uf {} /home/ftpuser2/public_html/ftparea/ \;