- Copy specific file type keeping the folder structure
- 7 Answers 7
- copy the file and keep full path
- 3 Answers 3
- How to Copy Files in Linux
- Copying Files in Linux
- Method 1: Graphical Way
- Method 2: Command-Line Way
- Copying Files in the Same Directory
- Copying Files in Different Directories
- Conclusion
- About the author
- Denis Kariuki
- Copy files and folders with full path in linux bash
Copy specific file type keeping the folder structure
I have a folder structure with a bunch of *.csv files scattered across the folders. Now I want to copy all *.csv files to another destination keeping the folder structure. It works by doing:
cp --parents *.csv /target cp --parents */*.csv" /target cp --parents */*/*.csv /target cp --parents */*/*/*.csv /target .
7 Answers 7
find has a very handy -exec option:
find . -name '*.csv' -exec cp --parents \ /target \;
Even though -execdir is safer than -exec , simply replacing one with the other does not preserve the folder structure as intended.
You could also use rsync for this.
$ rsync -a --prune-empty-dirs --include '*/' --include '*.csv' --exclude '*' source/ target/
If you want to keep empty directories from the source tree, skip the —prune-empty-dirs option:
$ rsync -a --include '*/' --include '*.csv' --exclude '*' source/ target/
If you do not want symlinks, modification dates, file permissions, owners etc. preserved, please replace -a with another combination of -rlptgoD . 😉
Also, the -R option can be added to copy the parent directory structure of source. (cf. my answer here.)
Unfortunately it seems that rsync is excruciating slow at finding matching files though. It takes like 100 more time than find. Is there anything that can be done about this?
You can use find and cpio in pass through mode
find . -name '*.csv' | cpio -pdm /target
This will find all .csv files in the current directory and below and copy them to /target maintaining the directory structure rooted in . .
find /path/to/files -name '*.csv' | cpio -pdm /target
it will find all of the file in /path/to/files and below and copy them to /target/path/to/files and below.
I tried all the answers top down up to this one, and this was the only one that worked on the first attempt
I found the GNU docs helpful: «In copy-pass mode, [requested by the -p option, cpio] reads the list of files to copy from the standard input; the directory into which it will copy them is given as a non-option argument.» . «-d Create leading directories where needed.» . «-m Retain previous file modification times when creating files.»
I want to do the same as the first line but copy all the contents of a folder and not only the csv files.
The cp command permits multiple source arguments:
CAVEAT: I’m using a recursive glob here; this is the globstar option in Bash 4+ and ksh , and is supported by default in zsh . Recursive globs do not match hidden files and folders, and the some implementations follow symlinks while others do not.
If your shell doesn’t support recursive globs, or if you’d prefer not to use them, you can do the following:
- *.csv */*.csv */*/*.csv */*/*/*.csv — this is of course very redundant and requires knowing how deep your directory structure is.
- $(find . -name ‘*.csv’) — This will match hidden files and folders. find also supports specifying whether or not symlinks are followed, which may be useful.
this is exactly what i tried (the recursive glob) and it found some but not all? pretty weird. I got the same exact result when using the npm copyfiles script but if i use the find command it finds everything.
@Randyaa I’ll need some more details on which files, exactly, weren’t found in order to help you. You may find the discussion here and continued here about the precise behavior of the recursive glob useful.
turns out recursive glob wasn’t enabled for some reason. I’ve never run into this before but i corrected it with just an execution of shopt -s globstar immediately before my command and all is well. Thanks for the follow up!
find -name «*.csv» | xargs cp —parents -t /target
If you have file names with spaces, add options -print0 and -0 like suggested in one of the comments:
find -name «*.csv» -print0 | xargs -0 cp —parents -t /target
Best answer with most simple syntax. Works just fine and is easy to remember. In many cases find [things] | xargs [do stuff] is very powerfull.
@pasztorpisti, is there any downside to that? If not should the answer not simply be edited to include your suggestion.
-R, —relative
Use relative paths. This means that the full path names specified on the command line are sent to the server rather than just the last parts of the filenames. This is particularly useful when you want to send several different directories at the same time. For example, if you used this command:
rsync -av /foo/bar/baz.c remote:/tmp/
. this would create a file named baz.c in /tmp/ on the remote machine. If instead you used
rsync -avR /foo/bar/baz.c remote:/tmp/
then a file named /tmp/foo/bar/baz.c would be created on the remote machine, preserving its full path. These extra path elements are called «implied directories» (i.e. the «foo» and the «foo/bar» directories in the above example).
rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
copy the file and keep full path
I need to copy the file to destination folder with it’s full path. I can do it on Linux (Red Hat/Centos) easily like this:
cp --parents /some/path/to/file /newdir
I’d need exactly the same feature on AIX 6.1. I tried few things but didn’t succeed yet. Any ideas for handy command to do the job?
If any of the answers solved your problem, please accept it by clicking the checkmark next to it. Thank you!
3 Answers 3
AIX’s native cp utility does not include the —parent option, as you’ve discovered.
One option would be to install and use rsync from the AIX Toolbox for Linux Applications software collection. You’d also need to install the popt RPM (as a dependency of rsync).
rsync -R /some/path/to/file /newdir/
To end up with /newdir/some/path/to/file .
As a home-grown option, you could write a wrapper function using ksh93 (for the array support) to emulate the behavior. Below is a bare-bones function as an example; it assumes you want to copy files with relative paths, and does not support any options:
relcp() < typeset -a sources=() [ "$#" -lt 2 ] && return 1 while [ "$#" -gt 1 ] do sources+=("$1") shift done destination=$1 for s in "$" do if [ -d "$s" ] then printf "relcp: omitting directory '%s'\n" "$s" continue fi sdir=$(dirname "$s") if [ "$sdir" != "." ] && [ ! -d "$destination/$sdir" ] then mkdir -p "$destination/$sdir" fi cp "$s" "$destination/$sdir" done unset sources s sdir >
How to Copy Files in Linux
Copying the files is likely a part of daily routine for anyone who is using Linux. You often want to copy a file across various directories. The easiest way of copying files in Linux is using the command line. For those who have issues with the command line, you can use the graphical interface, but it’s recommended to stick to the command line for more flexibility. Nonetheless, this guide will discuss the various ways of copying files in Linux.
Copying Files in Linux
You can use the graphical interface or command line to copy the files in Linux.
Method 1: Graphical Way
For anyone who is not comfortable with the command line, you can simply right-click on the file that you want to copy and select the copy option. Then, navigate to where you want to copy the file, right-click, and select the paste command.
Alternatively, you can use the “copy to” which opens the file system for you to navigate to your target directory.
Method 2: Command-Line Way
Copying the files in Linux is best when using the command line. Besides, Linux offers the cp command that you can use to copy the files from one directory to another by specifying its path.
There are various options that you can use with the cp command. The following is a quick cheat sheet:
- -v: Added to make the cp command verbose.
- -i: Added to make the cp command interactive, especially when copying the files into a directory that contains files with the same filename.
- -p: Added to copy a file and its attributes, such as access permissions and modification dates.
- -b: Added to create a backup of the file being copied to the destination folder, but with a different extension.
- -r: It specifies recursiveness and is used when you want to copy all files in a directory.
Let’s see how the cp command is used to copy the files.
Copying Files in the Same Directory
Suppose you want to copy the files to another directory in the same location. In that case, you only need to specify the file name or pattern and the target directory. We will use the files in the following image for this example:
In the given image, if we needed to copy the bash1.sh to the folder dir1, the command would be:
Note that we added the -v option for verbose.
Also, if we need to copy more than one file, you must separate the file names with a space and list all the files that you want to copy.
If you need to copy the files with the same extension, you can use the wildcard to match a given pattern. For instance, you could use the following command to copy all the text files. All files that match the pattern get copied to the specified directory.
Suppose you wanted to copy the files to a subdirectory in the current directory; you must specify the path. For instance, if dir1 has a subdirectory named test and you want to copy a file to it, we could use the following command:
If you copy the files to a directory that contains the same filename, you will end up overwriting the existing files unless you add the -i option for interactivity.
Let’s try to repeat the command in the previous example to see the error it raises and how you can choose to overwrite the existing files or not.
In the previous image, if you want to overwrite the files having the same names in the target directory, you must type y to the terminal, then press the enter key. If you don’t want to overwrite, press n.
If you want to create a copy of a file in the same directory, you must specify the target file and the name of the replica file. For instance, let’s create a copy of our file1.txt called replica.txt, and let’s retain its attributes. In that case, the command would be as shown in the following:
To create a backup of the file that you are copying, add the -b flag and note the new backup file that is created with a different extension. Let’s create a backup of bash1.sh to our destination folder. We now have a new backup named bash1.sh-
If you want to copy a directory and all the files, add the -r option and specify the path. For instance, in the following image, wecopied the linuxhint folder and all its contents to dir1.
Copying Files in Different Directories
When you must copy the files located in different directories, use the following syntax:
For instance, the command is shown in the following if we needed to copy a file in the /Pictures into the linuxhint sub-directory in the dir1.
The trick is to specify the exact path of the source file and the destination.
Conclusion
We’ve seen the various options that you have when it comes to copying the files in Linux. The commands described only need a little practice, and soon you will master how to copy the files in Linux using the command line.
About the author
Denis Kariuki
Denis is a Computer Scientist with a passion for Networking and Cyber Security. I love the terminal, and using Linux is a hobby. I am passionate about sharing tips and ideas about Linux and computing.
Copy files and folders with full path in linux bash
I was traying to make a simple script that takes a file or folder path and copies it, preserving the full path, in a folder called system next to the script. Exaple: Imagine I just have this folders in my system:
/home/my_user/copy_script /home/my_user/folder1/file1 /home/my_user/folder1/file2 /home/my_user/file3
If I pass as arguments the paths /home/my_user/folder1 and /home/my_user/file3 I want to get this folder structure as output: Files before runing the script
/home/my_user/copy_script /home/my_user/folder1/file1 /home/my_user/folder1/file2 /home/my_user/file3
/home/my_user/system/home/my_user/folder1/file1 /home/my_user/system/home/my_user/folder1/file2
/home/my_user/system/home/my_user/file3
The idea to have a copy of the config files in a folder that will be sync with gitlab preserving the same structure as my system. My script till now looks like this:
#!/bin/bash #need to implement relative paths #https://stackoverflow.com/questions/3963716/how-to-manually-expand-a- special-variable-ex-tilde-in-bash/29310477#29310477 #clears the old folder rm -r ./system #goes through all the arguments for var in "$@" do #It is a folder if [[ -d $var ]]; then mkdir -p "$PWD/system/$var" cp -R $var "$PWD/system/$var/.." echo "$var FOLDER" #It is a file elif [[ -f $var ]]; then mkdir -p "$PWD/system/$var" cp -R $var "$PWD/system/$var/.." echo "$var FILE" #The path is not ok else echo "$var ERROR" fi done
When it is a folder i think it works fine: Example: With the same folder structure as the beggining when we call copy_script /home/my_user/folder1 First creates the /home/my_user/system/home/my_user/folder1 path Then copies folder1 in /home/my_user/system/home/my_user/ But with files this does not work because it creates folders that I do not need and the I can’t copy the files. Example: calling copy_script /home/my_user/file3 will create /home/my_user/system/home/my_user/file3 path but then I can’t create the file because there is a folder with the same name. Could someone kindly explain me how to do this? Thanks.