bash copy files at extract path from original - linux

There is a set of file paths that i need to copy to some other location:
find . -name '*.txt':
/a/b/c/d/e/f/filea.txt
/a/b/c/d/e/g/h/fileb.txt
/a/b/c/d/e/k/l/filec.txt
I want to copy each of the files to the path that includes e and after e.g:
cp /a/b/c/d/e/f/filea.txt e/f/
The e path will always exists.
I need first to find all files.
How can find, extract everything after e from the path and copy at the same time?

Pipe the find output through
sed 's|\(.*\)\(\*\*e\*\*.*/\)\(.*\)|cp \1\2\3 \2|'
and if the result looks ok, pipe the sed output through sh. If by **e** you just meant e, the pattern is
sed 's|\(.*\)\(e.*/\)\(.*\)|cp \1\2\3 \2|'

You can use something like this. If the generated mkdir and cp commands look ok, you can remove the echo before them.
SOURCE="/a/b/c/d"
cd $SOURCE
DESTINATION="full/path/to/whatever"
for FILE in $(find . -name '*.txt'); do
DIR=$(dirname $FILE)
# create the intermediate directories if they don't exist
echo "mkdir -p $DESTINATION/$DIR"
echo "cp $FILE $DESTINATION/$DIR"
done

Related

Remove common strings in multiple files and copy them

I would like to copy and rename all files in a folder that are matching this pattern:
test.mp4.small.mp4
test2.mp4.small.mp4
test3.mp4.small.mp4
All files have in common that they end with .mp4.small.mp4.
I would like to copy them to a new folder and rename them - the result should be:
test.mp4
test2.mp4
test3.mp4
Attempt:
find . -name '*.mp4.small.mp4' -exec bash -c 'echo cp $0 ${0/PATH/}' {} \;
But this does not rename it.
Use the parameter expansion syntax for removing the shortest string from the beginning upto delimiter . of syntax ${word%string} as
find . -name '*.mp4.small.mp4' -exec bash -c 'echo cp $0 ${0%.mp4.small.mp4}.mp4' {} \;
Also I assume, you knowingly have added the echo to just troubleshoot how the renamed string looks like. To actually copy the files, drop it in the final command.
rename 's/.mp4.small//' *mp4.small.mp4
will not overwrite by default.
to test just to make sure:
ls *mp4.small.mp4 | sed 's/.mp4.small//' #list resulting file names

Rename all files in multiple folders with some condition in single linux command os script.

I have multiple folders with multiple files. I need to rename those files with the same name like the folder where the file stored with "_partN" prefix.
As example,
I have a folder named as "new_folder_for_upload" which have 2 files. I need to convert the name of these 2 files like,
new_folder_for_upload_part1
new_folder_for_upload_part2
I have so many folders like above which have multiple files. I need to convert all the file names as I describe above.
Can anybody help me to find out for a single linux command or script to do this work automatically?
Assuming bash shell, and assuming you want the file numbering to restart for each subdirectory, and doing the moving of all files to the top directory (leaving empty subdirectories). Formatted as script for easier reading:
find . -type f -print0 | while IFS= read -r -d '' file
do
myfile=$(echo $file | sed "s#./##")
mydir=$(dirname "$myfile")
if [[ $mydir != $lastdir ]]
then
NR=1
fi
lastdir=${mydir}
mv "$myfile" "$(dirname "$myfile")_part${NR}"
((NR++))
done
Or as one-line command:
find . -type f -print0 | while IFS= read -r -d '' file; do myfile=$(echo $file | sed "s#./##"); mydir=$(dirname "$myfile"); if [[ $mydir != $lastdir ]]; then NR=1; fi; lastdir=${mydir}; mv "$myfile" "$(dirname "$myfile")_part${NR}"; ((NR++)); done
Beware. This is armed, and will do a bulk renaming / moving of every file in or below your current work directory. Use at your own risk.
To delete the empty subdirs:
find . -depth -empty -type d -delete

Execute multiple commands on target files from find command

Let's say I have a bunch of *.tar.gz files located in a hierarchy of folders. What would be a good way to find those files, and then execute multiple commands on it.
I know if I just need to execute one command on the target file, I can use something like this:
$ find . -name "*.tar.gz" -exec tar xvzf {} \;
But what if I need to execute multiple commands on the target file? Must I write a bash script here, or is there any simpler way?
Samples of commands that need to be executed a A.tar.gz file:
$ tar xvzf A.tar.gz # assume it untars to folder logs
$ mv logs logs_A
$ rm A.tar.gz
Here's what works for me (thanks to Etan Reisner suggestions)
#!/bin/bash # the target folder (to search for tar.gz files) is parsed from command line
find $1 -name "*.tar.gz" -print0 | while IFS= read -r -d '' file; do # this does the magic of getting each tar.gz file and assign to shell variable `file`
echo $file # then we can do everything with the `file` variable
tar xvzf $file
# mv untar_folder $file.suffix # untar_folder is the name of folder after untar
rm $file
done
As suggested, the array way is unsafe if file name contained space(s), and also doesn't seem to work properly in this case.
Writing a shell script is probably easiest. Take a look at sh for loops. You could use the output of a find command in an array, and then loop over that array to perform a set of commands on each element.
For example,
arr=( $(find . -name "*.tar.gz" -print0) )
for i in "${arr[#]}"; do
# $i now holds each of the filenames output by find
tar xvzf $i
mv $i $i.suffix
rm $i
# etc., etc.
done

Recursively rename .jpg files in all subdirectories

I am on a Linux system and I am trying to rename all .jpg files in many subdirectories to sequential filenames, so all the jpeg files in each subdirectory are renamed 0001.jpg, 0002.jpg, etc. I have a 'rename' command that works in a single directory:
rename -n 's/.*/sprintf("%04d",$::iter++ +1).".jpg"/e' *.jpg
I am trying to use it like this:
for i in ls -D; do rename -n 's/.*/sprintf("%04d",$::iter++ +1).".jpg"/e' *.jpg; done
but for output I get this:
*.jpg renamed as 0001.jpg
for each subdirectory. What am I doing wrong?
You need to put the command in backticks (or use the $( ... ) bash syntax) in order
to iterate over its output. Also use the $i variable together with the *.jpg file
name pattern, e.g.
for i in `ls -D`
do
rename -n 's/.*/sprintf("%04d",$::iter++ +1).".jpg"/e' $i/*.jpg
done
however, for this scenario you want to iterate over all the subdirectories, and you are
better of using the find command:
for i in `find . -type d`; do rename ...
It seems to me you've forgot to change a current working directory so it should looks like
for i in *; do
[ -d "$i" ] || continue
pushd "$i"
# rename is here
popd
done

Get folder name and rename file name tr Linux bash

I have a script that changes the file name. It takes a directory name and added to the file name. By the way, using tr replaces a string:
0004 the name of the directory (this directory is a script)
- DSC_1234.jpg
result 0004_1234.jpg
The script works if I am in a particular directory. I wanted to change a name yet in subdirectories
#!/bin/bash
CURRENT=`pwd`
BASENAME=`basename $CURRENT`
echo $BASENAME
for i in ./*DSC*;do mv -- "$i" "${i//DSC/$BASENAME}";done
The following should work in subdirectories:
for i in $(find . -type f); do dir="$(dirname ${i#./})"; mv "$i" "${i//DSC/$(basename $dir)}"; done
You probably want to use find on your bash script (call that script your_script.sh):
find $ROOT_DIR -type d -exec your_script.sh \;

Resources