How to copy in bash all directory and files recursive? - bash

I have script:
find ./SourceFolder/ -maxdepth 4 -exec cp -R '{}' ./DestFolder/ \;
SourceDir contains also sub-folders.
Problem that in DestFolder not only all tree, but in up level all another levels and files.
How to fix ?

cp -r ./SourceFolder ./DestFolder

code for a simple copy.
cp -r ./SourceFolder ./DestFolder
code for a copy with success result
cp -rv ./SourceFolder ./DestFolder
code for Forcefully if source contains any readonly file it will also copy
cp -rf ./SourceFolder ./DestFolder
for details help
cp --help

also try this cp -r ./dist/* ./out;
this command will copy dist/* files to out dir;

You might find it handy to keep your attributes set
cp -arf ./SourceFolder ./DestFolder

Related

Copy all files with a certain extension from all subdirectories and preserving structure of subdirectories

How can I copy specific files from all directories and subdirectories to a new directory while preserving the original subdirectorie structure?
This answer:
find . -name \*.xls -exec cp {} newDir \;
solves to copy all xls files from all subdirectories in the same directory newDir. That is not what I want.
If an xls file is in: /s1/s2/ then it sould be copied to newDir/s1/s2.
copies all files from all folders and subfolders to a new folder, but the original file structure is lost. Everything is copied to a same new folder on top of each other.
You can try:
find . -type f -name '*.xls' -exec sh -c \
'd="newDir/${1%/*}"; mkdir -p "$d" && cp "$1" "$d"' sh {} \;
This applies the d="newDir/${1%/*}"; mkdir -p "$d" && cp "$1" "$d" shell script to all xls files, that is, first create the target directory and copy the file at destination.
If you have a lot of files and performance issues you can try to optimize a bit with:
find . -type f -name '*.xls' -exec sh -c \
'for f in "$#"; do d="newDir/${f%/*}"; mkdir -p "$d" && cp "$f" "$d"; done' sh {} +
This second version processes the files by batches and thus spawns less shells.
This should do:
# Ensure that newDir exists and is empty. Omit this step if you
# don't want it.
[[ -d newDir ]] && rm -r newDir && mkdir newDir
# Copy the xls files.
rsync -a --include='**/*.xls' --include='*/' --exclude='*' . newDir
The trick here is the combination of include and exclude. By default, rsync copies everything below its source directory (. in your case). We change this by excluding everything, but also including the xls files.
In your example, newDir is itself a subdirectory of your working directory and hence part of the directory tree searched for copying. I would rethink this decision.
NOTE: This would not only also copy directories whrere the name ends in .xls, bur also recreated the whole directory structure of your source tree (even if there are no xls files in it), and populate it only with xls files.
Thanks for the solutions.
Meanwhile I found also:
find . -name '*.xls' | cpio -pdm newDir

Bash: CP will consider file with extension as duplicate as file without it

I'm running
cp -dR "${SOURCE_DIR}" "${OUTPUT_DIR}"
And there's one place with a file something and something.exe.
CP is failing because it considers both of them the same file. Can this be forced somehow?
You can use this find-based alternative :
find source/ -type d -exec mkdir target/{} \; -o -type f -exec cp -d {} target/{} \;
It recurses over the content of the source/ directory, using mkdir to create directories it encounters in the target directory and cp to copy the files one by one.
I expect this will be quite slower than your original cp -R would have been. If you've got the rsync binary available (not by default with git bash AFAIK) you should give it a try, it might not have the same unfortunate interaction with git bash and its .exe simplification that you found in cp -R and should be faster than my solution.

In bash, cp does copy dot files while using wildcard? Which option should I use

When I use
cp -r source dest,
the dot files as in .gitIgnore or any .xyz are ignored. When I use
cp -r source/.xyz dest,
then they are copied. Which option with cp can copy all the files including the dot files while using the wildcard *?
You can use the wildcard like cp -r .[^.]*
Thats because your bash is built to ignore the hidden files and cp command just don't get the hidden arguments. Thats how its supposed to work .. :)
As for me the most universal way:
cp -a /source/. /destination/
Or if you are inside of a source folder:
cp -a . /destination/
While using a wildcard *, you can try the command cp source/*.* destination/ to copy all the hidden files too.
If you want to include unhidden directories in the cp command you can try the below command
cp -r source/. destination/
Note the . at the end of source. That includes all the files and directories in the source including hidden ones.
Or
cp -r source/{.,}* destination/
x{.,}y is converted to x.y and xy. In your case it will be source/.* and source/*

Shell script to extract all zip files in a directory and its sub directory, and copy the extracted files into another folder with same hierarchy

I have some zip files like below.
./etk/test/etf_time_series_am_update.zip
./etk/test/etf_time_series_am_delete.zip
./etk/dir1/etf_time_series_am_update.zip
./etk/dir1/etf_time_series_am_delete.zip
./etk/dir1/dir2/etf_time_series_am_update.zip
./etk/dir1/dir2/etf_time_series_am_delete.zip
./etk/dir1/dir2/dir3/etf_time_series_am_update.zip
./etk/dir1/dir2/dir3/etf_time_series_am_delete.zip
I want these files to unzip and store into the another folder. like
./newf/test/etf_time_series_am_update.txt
./newf/test/etf_time_series_am_delete.txt
./newf/dir1/etf_time_series_am_update.txt
./newf/dir1/etf_time_series_am_delete.txt
./newf/dir1/dir2/etf_time_series_am_update.txt
./newf/dir1/dir2/etf_time_series_am_delete.txt
./newf/dir1/dir2/dir3/etf_time_series_am_update.txt
./newf/dir1/dir2/dir3/etf_time_series_am_delete.txt
I tried with the find command and able to unzip, but couldn't copy in the destination folder.
I tried to unzip by following command. but have no idea about copy into the destination folder.
find -name '*.zip' -exec sh -c 'unzip -d "${1%.*}" "$1"' _ {} \;
This might be works for you.
find . -name "*.zip" | while read filename; do unzip -o -d "`dirname "$filename" | sed -r 's/etk/newf/g'`" "$filename"; done;
You may also get better solution by referring following links.
Finding-multiple-files-recursively-renaming
Recursively unzip

Read a file permission and apply to another in shell

I am writing a script and I want to apply the permissions of a given file to another, given that the owner of both files is the same. The files can be huge, so moving the file contents using
cp dest tmp
rm dest
cp source dest
echo tmp > dest
rm tmp
is not an option.
Does your chmod support the --reference option? It does exactly what you need.
FILE1="$HOME/.bashrc"
FILE2="$HOME/.profile"
FPERM=`stat -c "%a" "$FILE1"`
chmod $FPERM "$FILE2"
PS. If also ownership:
FUID=`stat -c "%U" "$FILE1"`
FGID=`stat -c "%G" "$FILE1"`
chown $FUID:$FGID "$FILE2"

Resources