Copying files based on modification date in Linux
Use the -exec
option for find
:
find . -mtime -90 -exec cp {} targetdir \;
-exec
would copy every result returned by find
to the specified directory (targetdir
in the above example).
Copy Folders and its files with specific date in Linux
It will work.
find A -mtime -18 -mtime +1 -exec cp \{\} B/ \;
Find and copy specific files by date
Would you please try the following:
#!/bin/bash
dir="/var/www/my_folder"
second=$(ls -t "$dir/"*.log | head -n 2 | tail -n 1)
if [[ $second =~ .*_([0-9]{4}_[0-9]{2}_[0-9]{2})\.log ]]; then
capturedate=${BASH_REMATCH[1]}
cp -p "$dir/"*"$capturedate".dmp /tmp
fi
second=$(ls -t "$dir"/*.log | head -n 2 | tail -n 1)
will pick the
second to last log file. Please note it assumes that the timestamp
of the file is not modified since it is created and the filename
does not contain special characters such as a newline. This is an easy
solution and we may need more improvement for the robustness.- The regex
.*_([0-9]{4}_[0-9]{2}_[0-9]{2})\.log
will match the log
filename. It extracts the date substring (enclosed with the parentheses) and assigns the bash variable${BASH_REMATCH[1]}
to it. - Then the next
cp
command will do the job. Please be cateful
not to include the widlcard*
within the double quotes so that
the wildcard is properly expanded.
FYI here are some alternatives to extract the date string.
With sed
:
capturedate=$(sed -E 's/.*_([0-9]{4}_[0-9]{2}_[0-9]{2})\.log/\1/' <<< "$second")
With parameter expansion of bash (if something
does not include underscores):
capturedate=${second%.log}
capturedate=${capturedate#*_}
With cut
command (if something
does not include underscores):
capturedate=$(cut -d_ -f2,3,4 <<< "${second%.log}")
Copy N days old files on Linux
You can use mtime
within your find command:
find /tmp/temp/ -type f -mtime -2 -name *files.csv -exec cp -u {} /home/dir/Desktop/dir1/ \;
This would copy only files with a modified time within the last two days of the system time.
-mtime n
File's data was last modified n*24 hours ago
Giving a file/directory the same modification date as another
You have some options:
- Use
touch -t STAMP -m file
if you want to change the time - Use
cp --preserve=timestamps
if you're copying the files and want to preserve the time - Use
touch -r
to set the time to a "reference" file
Copy files with date/time range in filename
If your time span is reasonably limited, just inline the acceptable file names into the single find
command.
find . \( -false $(for ((iTime=starttime;iTime<=endtime;iTime++)); do printf ' %s' -o -name "*$iTime*"; done) \) -exec cp --parents \{\} ${dst} \;
The initial -false
predicate inside the parentheses is just to simplify the following predicates so that they can all start with -o -name
.
This could end up with an "argument list too long" error if your list of times is long, though. Perhaps a more robust solution is to pass the time resolution into the command.
find . -type f -exec bash -c '
for f; do
for ((iTime=starttime;iTime<=endtime;iTime++)); do
if [[ $f == *"$iTime"* ]]; then
cp --parents "$f" "$0"
break
fi
done' "$dst" {} +
The script inside -exec
could probably be more elegant; if your file names have reasonably regular format, maybe just extract the timestamp and compare it numerically to check whether it's in range. Perhaps also notice how we abuse the $0
parameter after bash -c '...'
to pass in the value of $dst
.
ext4 copy file to directory without changing directory timestamp
One option is to save and restore the timestamp:
# Save current modification time
timestamp=$(stat -c @%Y mydir)
[.. copy/sync files ..]
# Restore that timestamp
touch -d "$timestamp" mydir
Copying the files - for each date from source into target directory with same date
edit:
#!/bin/bash
path=$1
dstpath=$2
files=$(ls $path)
for file in $files
do
IFS='.' read -ra fs <<< "$file"
fname=${fs[0]}
filename=$(echo $fname | awk -F '\_' '{print $3}')
ymd=${filename::8}
echo "ymd:" $ymd
if [ -e $dstpath$ymd ]
then
echo "exsits"
else
echo "mkdir"
mkdir -p $dstpath/$ymd
fi
cp $path/$file $dstpath/$ymd/
done
note: the two args should NOT end with /
: use/home/user/test
not /home/user/test/
old answer:
I write a scriptmy_copy.sh
, it works well for me.
#!/bin/bash
path=$1
dstpath=$2
files=$(ls $path)
for file in $files
do
IFS='.' read -ra fs <<< "$file"
fname=${fs[0]}
ymd=${fname: -8}
cp $path/$file $dstpath/$ymd/
done
Usage
$ ls /home/user/test
Test_2G3G_20210601.pdf
Test_2G3G_20210602.csv
$ ls /home/user/dst
20210601
20210602
$ ./my_copy.sh /home/user/test /home/user/dst
Related Topics
Black Color Showing on Cmy Channels When Converted to Cmyk Using Ghostscript
Every Command Is Returning 'Bash: <Command>: Command Not Found...'
In Unix, How to Run 'Make' in a Directory Without Cd'Ing to That Directory First
How to Make Find and Printf Works in Bash Script
How to Append to a File Using X86-64 Linux System Calls
About Process Control Block in Os
Escape Single Quotes in Shell Script
Trailing Arguments with Find -Exec {} +
Adding a Header into Multiple .Txt Files
I Want to Remove Multiple Line of Text on Linux
Grabbing Specific Sections of Text from a String
Why Is Cpu-Cycles Much Less Than CPU Current Frequency
How to Install Cargo on a Rhel Linux Server
How to Check the Bios Version or Name in Linux Through a Command Prompt
How to Determine the Current Ip from a Known MAC Address