Bash script to rename files with current timestamp - bash

master_sheet_2022_03_25_1141.csv
master_sheet_2021_03_30_1034.csv
master_sheet_2021_03_31_1857.csv
master_sheet_2021_03_31_1930.csv
master_sheet_2021_03_31_2037.csv
master_sheet_2021_03_31_2109.csv
For each file in above directory, rename the file but append master_sheet
master_sheet__$(date "+%Y.%m.%d-%H.%M.%S").csv"
eg: master_sheet__2022_04_06_09:30
Here is my current script
#!/bin/bash
find . -type f -name "*.csv" | \
while read -r files; do
mv "$files" "${files%.*}_$(date "+%Y.%m.%d-%H.%M.%S").csv"
# for files in *; do echo "${files%.*}"; done
done
Current output
master_sheet_2022_03_22_1351_2022.04.06-09.14.00_2022.04.06-09.19.27_2022.04.06-09.20.12
master_sheet_2022_03_29_1043_2022.04.06-09.14.00_2022.04.06-09.19.27_2022.04.06-09.20.12

Related

Rename files to unique names and move them into a single destination directory

i have 100s of directories with same filename of content.html along with other files.
I am trying to copy all these content.html files under 1 directory, but since they have same name, it overwrites each other
so how can i rename and move all these under 1 directory
Eg:
./0BD3D9D2-F8B1-4472-95C2-13319650A45C:
card.png content.html note.xhtml quickLook.png snippet.txt
./0EA34DB4-CD56-42BE-91DA-F631E44FB6E0:
card.png content.html note.xhtml quickLook.png related snippet.txt
./1A33F29E-3938-4C2F-BA99-6B98FD045742:
card.png content.html note.xhtml quickLook.png snippet.txt
command i tried:
rename content.html to content
find . -type f | grep content.html | while read f; do mv $f ${f/.html/}; done
append number to filename "content" to make it unique
find . -type f | grep content | while read f; do i=1; echo mv $f $f$i.html; i=i+1; done
MacBook-Pro$ find . -type f | grep content | while read f; do i=1; echo mv $f $f$i.html; i=i+1; done
mv ./0BD3D9D2-F8B1-4472-95C2-13319650A45C/content ./0BD3D9D2-F8B1-4472-95C2-13319650A45C/content1.html
mv ./0EA34DB4-CD56-42BE-91DA-F631E44FB6E0/content ./0EA34DB4-CD56-42BE-91DA-F631E44FB6E0/content1.html
mv ./1A33F29E-3938-4C2F-BA99-6B98FD045742/content ./1A33F29E-3938-4C2F-BA99-6B98FD045742/content1.html
once above step is successful, i should be able do this to achieve my desired output:
find . -type f | grep content | while read f; do mv $f ../; done
however, i am sure i can do this in 1 step command and also my step 2 is not working (incrementing i)
any idea why step2 is not working??
bash script:
#!/bin/bash
find . -type f -name content.html | while IFS= read -r f; do
name=$(basename $f)
((++i))
mv "$f" "for_content/${name%.*}$i.html"
done
replace for_content with your destination folder name
Suppose in your base directory, you create a folder named final for storing
content.html files, then do something like below
find . -path ./final -prune -o -name "content.html" -print0 |
while read -r -d '' name
do
mv "$name" "./final/content$(mktemp -u XXXX).html"
# mktemp with -u option just creates random characters, or it is just a dry run
done
At the end you'll get all the content.html files under ./final folder in the format contentXXXX.html where XXXX are random characters.
Note:-path ./final -prune -o in find prevents it from descending to our results folder.
The inode of the of the files should be unique and so you could use the following:
find $(pwd) -name "content.html" -printf %f" "%i" "%p"\n" | awk '{ system("mv "$3" <directorytomoveto>"$2$1) }'
I'd use something like this:
find . -type f -name 'test' | awk 'BEGIN{ cnt=0 }{ printf "mv %s ./output-dir/content_%03d.txt\n", $0, cnt++ }' | bash;
You can replace ./output-dir/ with your destination directory
Example:
[root#sl7-o2 test]# ls -R
.:
1 2 3 output-dir
./1:
test
./2:
test
./3:
test
./output-dir:
[root#sl7-o2 test]# find . -type f -name 'test' | awk 'BEGIN{ cnt=0 }{ printf "mv %s ./output-dir/content_%03d.txt\n", $0, cnt++ }' | bash;
[root#sl7-o2 test]# ls ./output-dir/
content_000.txt content_001.txt content_002.txt
You can use shopt -s globstar to grab all content.html files recursively and then use a loop to rename them:
#!/bin/bash
set -o globstar
counter=0
dest_dir=/path/to/destination
for f in **/content.html; do # pick up all content.html files
[[ -f "$f" ]] || continue # skip if not a regular file
mv "$f" "$dest_dir/content_$((++counter).html"
done

search file and print to the same directory

I want to search a file by name and run a python script on it and finally print the output to the directory that contains the file. The structure looks like
dir_a/common.txt
dir_b/common.txt
dir_c/common.txt
And so far I have came up with
find . -maxdepth 2 -name "common.txt" -exec cat "{}" \; | ~/myscript.py
myscript.py prints to the stdout. But how can I redirect the output to
dir_a/out.txt
dir_b/out.txt
dir_c/out.txt
Maybe small script runmypy.sh:
#!/bin/bash
topdir="${1:-.}"
while IFS= read -r -d '' file; do
dir=$(dirname "$file")
/path/to/myscript.py < "$file" >"$dir/out.txt"
done < <(find "$topdir" -maxdepth 2 -type f -name "common.txt" -print0)

Rename files with a suffix with name of its folder

Each folder has a .mkv or .avi file.
E.g:
Sommerferien201308/eins.avi
Sommerferien201309/eins.mkv
Herbst201401/film.avi
Herbst201402/krz.mkv
Renaming to:
Sommerferien201308/Sommerferien201308.avi
Sommerferien201309/Sommerferien201309.mkv
Herbst201401/Herbst201401.avi
Herbst201402/Herbst201402.mkv
How can I rename the filename to the name of its folder?
Of course every foldername is unique. And too much to do it manually for each file/folder.
I Would try with find.
find . -type d -name "" -exec cd "" && mv {} \;
But i dont know how to select the folder name and how to make the .avi or .mkv selection and how to store the selected folder name..
You can use this find command from base folder of your folders that contain *.avi and *.mkv files:
while IFS= read -rd '' f; do
(
IFS=/
arr=($f)
if [[ $f != *"/${arr[len-2]}"* ]]; then
len=${#arr[#]}
ext="${arr[len-1]##*.}"
cd "$(dirname "$f")" && echo mv "${arr[len-1]}" "${arr[len-2]}.$ext"
fi
)
done < <(find . \( -name '*.mkv' -o -name '*.avi' \) -print0)
When you're satisfied with the output remove echo before mv.

How to print the number of locations of file found

Prompt the user for a file name, without the path (Ex: xyz.out)
- Using the find command, provide the full path to the file
- At the end, “print number of locations of that file found”
- If it’s not found, then display “not found
and this is my script
#! /bin /bash
echo "please enter your file name"
read filename
if [ -f $filename ];
then
echo "file $filename found"
find $PWD -type f | grep $filename
#find "$(cd ..; pwd)" -name $filename
else
echo "file $filename was not found"
fi
but the thing is At the end, i need to “print number of locations of that file found”
help me out with this
Something like this to get the count:
find $PWD -type f -name $filename 2>/dev/null | wc -l
This should work:
find "$PWD" -type f -name "$fname" |grep "" -c
In trying to keep it as short as possible, one approach with Posix shell would be to fill a temporary file with the file names returned by find, cat the file to provide your output, and use wc to provide the line count (note: you use your own pattern instead of "*cmpf*" shown below):
$ find . -name "*cmpf*" -printf "%P\n" >tmp; cat tmp; c=$(wc -l <tmp); \
rm tmp; printf "[%s] files found\n" $c
cmpf1f2.c
cmpf1f2_2.c
bin/cmpf1f2_2
bin/cmpf1f2
snip/cmpf1f2_notes.txt
cmpf1f2_for.c
[6] files found
If bash is available, another approach is to read the matching files into an array and then use the number of elements as your count. Example:
$ a=( $(find . -name "*cmpf*" -printf "%P\n") ); printf "%s\n" ${a[#]}; \
printf -- "--\n'%s' files found.\n" ${#a[#]}
cmpf1f2.c
cmpf1f2_2.c
bin/cmpf1f2_2
bin/cmpf1f2
snip/cmpf1f2_notes.txt
cmpf1f2_for.c
--
'6' files found.
Both approaches give you both the files and directories in which they reside as well as the count of the files returned.
Note: if you would like ./ before each file and directory names, use the %p format instead of %P above.

Bash: Find, copy and rename files

I am trying to copy files (on the same server) created in the last 24 hours using the filename (Unix timestamp):
find /srv/docs/files/ -type f -iname '*.pdf' -mtime -1 -exec cp {} /srv/docs/pdf \;
However, I would like to extend this further. I would like to accomplish the following:
All files are named in this manner 1425787200.pdf. I would like to rename the file Sunday-0400.pdf
I would would like to create a new directory /srv/docs/pdf/day/time/ .
A file named 1425787200.pdf would end up in /srv/docs/pdf/Sunday/0400/Sunday-0400.pdf
Additionally, if the file already exists, an incremental number should be added to the file. eg Sunday-0400-1.pdf, Sunday-0400-2.pdf
Any help would be appreciated.
To change file name 1425787200.pdf to /srv/docs/pdf/Sunday/0400/Sunday-0400.pdf use something like this:
#!/usr/bin/bash
file=1425787200.pdf
day=$(date +"%A" -d "#${file%.*}")
time=$(date +"%H%M" -d "#${file%.*}")
new_file=/srv/docs/pdf/$day/$time/$day-$time.pdf
if [ -e "$new_file" ]; then
num_file=${new_file%.*}
num=1
while [ -e "${num_file}-${num}.pdf" ]; do
num=$(( num + 1 ))
done
new_file=${num_file}-${num}.pdf
fi
mv $file $new_file
this will also number duplcates.

Resources