Copying Files Based on Modification Date in Linux

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



Leave a reply



Submit