Linux: find a file in a directory, backup it with another name, replace it - linux

In Linux I'm trying to find a file in a directory, backup it with another name and, then, replace it with another one.
I tried the first two actions with these commands
find foldername -name filename.html; -exec sed -i .bak;
but it's says
bash: -exec: command not found

Try this:
find foldername -name filename.html -exec cp -vp {}{,.bak} \; -exec truncate -s 0 {} \;
This uses find's exec option like it looks like you tried to use. Then cp copies the file (specified with {}) and appends .bak to the copy and preserves what it can with the p option:
preserve the specified attributes (default:
mode,ownership,timestamps), if possible additional attributes:
context, links, xattr, all
This leaves the original file in place as well.

You can do the following:
find . -name 'FILE_PATTERN_HERE' | xargs -I file_name cp file_name file_name.bkp
You can pipe the output of find command to cp using xargs. Here file_name acts as the output of find.
Example
find . -name 'logback.xml*'
Output:
./logback.xml
./apache-cassandra-3.11.1/conf/logback.xml
After running the command
find . -name 'logback.xml*' | xargs -I file_name cp file_name file_name.bkp
find . -name 'logback.xml*'
Output:
./logback.xml
./apache-cassandra-3.11.1/conf/logback.xml
./apache-cassandra-3.11.1/conf/logback.xml.bkp
./logback.xml.bkp

Related

Copy recursive files of all the subdirectories

I want to copy all the log files from a directory which does not contain log files, but it contains other subdirectories with log files. These subdirectories also contain other subdirectories, so I need something recursive.
I tried
cp -R *.log /destination
But it doesn't work because the first directory does not contains log files. The response can be also a loop in bash.
find /path/to/logdir -type f -name "*.log" |xargs -I {} cp {} /path/to/destinationdir
Explanation:
find searches recursively
-type f tells you to search for files
-name specifies the name pattern
xargs executes commands
-I {} indicates an argument substitution symbol
Another version without xargs:
find /path/to/logdir -type f -name '* .log' -exec cp '{}' /path/to/destinationdir \;

How to use scp with xargs?

I am trying to move very big file from one host to another host. Also the file names are too large so I have to use xargs. Also all the sub directories need to be copied also
I am using the below command in the source host current directory
find . -name "*" -type f -print0 | xargs -0 scp -r UserName#host:/path/to/destination
but it is throwing below error
scp: /path/to/destination: not a regular file
you need to use {} to put the src filename before the destination. Here is the new command:
find . -name "*" -type f -print0 | xargs -0 -I {} scp -r {} UserName#host:/path/to/destination

Stuck trying to copy files to a new directory under specific guidelines

I'm trying to copy all files from a folder that start with a capital letter into another folder.
So far i've used the find command to actually find the files
find /examplefolder -type f -name "[[:upper:]]*"
and i'm able to find them no problem
I tried to just replace the find command with cp and that does not work then i tried to pipe into the cp command and I failed yet again
Use the -exec option for find
find /examplefolder -type f -name "[[:upper:]]*" -exec cp {} /my/new/shiny/folder/ \;
I was able to do it by piping in to cp with xargs and the -I argument
find /examplefolder -type f -name "[[:upper:]]*" | xargs -I % cp % /copied_directory

how to cp files with spaces in the filename when files are provided by find

I would like to ensure that all files found by find with a given criteria are properly copied to the required location.
$from = '/some/path/to/the/files'
$ext = 'custom_file_extension'
$dest = '/new/destination/for/the/files/with/given/extension'
cp 'find $from -name "*.$ext"' $dest
The problem here is that, when a file found with the proper extension and it is containing space cp cannot copy it properly.
You don't do that. You can't splat filenames with spaces that way.
You either get to use something from http://mywiki.wooledge.org/BashFAQ/001 to read the output from find line-by-line or into an array or you use find -exec to do the copy work.
Something like this:
from='/some/path/to/the/files'
ext='custom_file_extension'
dest='/new/destination/for/the/files/with/given/extension'
find "$from" -name "*.$ext" -exec cp -t "$dest" {} +
Using -exec command + here means that find will only execute as many cp commands as it needs based on command length limits. Using -exec command ; here would run one cp-per-file-found (but is more portable to older systems).
See comment from gniourf_gniourf about the use of -t in that cp command to make -exec command + work correctly.
Use -exec:
find "$from" -name "*.$ext" -exec cp {} "$dest" \;
you need to copy file one by one:
for file in "$from"/*."$ext"; do
cp "$file" "$dest"
done
I just use glob here, and it's enough and complete. I think find may introduce problem if the file name contains funny character.
The solution for this sort of problem is xargs -0 and the -print0 flag for find.
-print0 instructs find to print the results with a NUL character termination, instead of a newline, while -0 for xargs tells it expect input in that format.
Finally, the -J option for xargs allows one to put the arguments in the right place for a copy.
find "$from" -name "*.$ext" -print0 | xargs -0 -J % cp % "$dest"
It's better to use -exec argument of find command to do this:
find . -type f -name "*.ext" -exec cp {} ./destination_dir \;
I've checked this case with files containing spaces and it's work for me. Also don't forger to point out '-type f' if you want to find only files, not directories.

Linux script Loop

I want to create a loop in Linux script that will go thru the folders in one directory and will copy photos to one folder and will overwrite photos that have the same name. Can anyone point me in the write direction?
find /path/to/source -type f -exec cp -f {} /path/to/destination \;
Would that work? Keep in mind, that will overwrite files without asking.
If you want it to confirm with you before overwriting, use the -i flag (for interactive mode) in the cp command.
find /path/to/source -type f | xargs -I {} file {} | grep <JPEG or image type> | cut -d ":" -f1 | xargs -I {} cp -rf {} /path/to/destination
With this you can find tune your copy with selecting only the image type.
Actually, you need not to loop through folders for finding photos using script, find command will do that job for you.
Try using find with xargs and cp
find source_dir -type f -iname '*.jpg' -print0 | xargs -0 -I {} cp -f {} dest_dir
Replace *.jpg with format of your photo files. (e.g. *.png etc.)
Note the use of -f option of cp, since you want to overwrite photos with the same name

Resources