Bash脚本从子目录移动最新的特定文件类型

时间:2015-09-02 23:05:29

标签: shell

  • 从当前目录中搜索所有子目录。
  • 仅定位特定的文件扩展名类型。
  • 仅将其中带有时间戳的最新文件复制到另一个目录。

    找到。 -mindepth 2 -name" * .ZIP" -exec cp {} tempZIP` \;

唯一的问题是我不知道怎么告诉它只抓取每个子目录中的最新文件。文件格式为:

2015-09-01_10-48-09.941 + 0000

for files in */; do

echo "Beginning of for loop"
echo "The current directory is $files"

cd $files
currentDirectory=$(pwd)
echo "Current working directory: $currentDirectory"

echo "Removing excess files from acqusition zips..."
rm *.csv *.tfr *.ini *.log
rm _Background.mca _Escape.mca _Gaussfit.mca _SumPeak.mca

echo "Removing the oldest MCA files..."
theDate=$(date +"LIVE_DATA_%Y-%m-%d_%H-%M-%S.000+0000.MCA")
echo "The date timestamp is $theDate"


for file in *; do
  echo "Current file is: $file"

  file=${file/.[0-9][0-9][0-9]/}
  if [[ $theDate -gt $max ]] ; then
    max=$theDate
    latest="$file"
  fi
done
echo "Latest: $latest"

echo "Moving up a folder"
cd ../
movedDirectory=$(pwd)
echo "Moved directory $movedDirectory"

echo "End of for loop"
done

如何比较我指定的日期格式和文件?

The current directory is U-500.0.0.2015-09-01_10-49-01-34/
Current working directory: /Users/user/Desktop/WatsonErrorLogs/v448/AlloyScript/temp/U-500.0.0.2015-09-01_10-49-01-34
Removing excess files from acqusition zips...
rm: *.csv: No such file or directory
rm: *.tfr: No such file or directory
rm: *.ini: No such file or directory
rm: *.log: No such file or directory
rm: _Background.mca: No such file or directory
rm: _Escape.mca: No such file or directory
rm: _Gaussfit.mca: No such file or directory
rm: _SumPeak.mca: No such file or directory
Removing the oldest MCA files...
The date timestamp is LIVE_DATA_2015-09-08_11-31-59.000+0000.MCA
Current file is: LIVE_DATA_2015-09-01_10-49-04.446+0000.MCA
./test.sh: line 46: [[: LIVE_DATA_2015-09: value too great for base (error token is "09")
Current file is: LIVE_DATA_2015-09-01_10-49-09.916+0000.MCA
./test.sh: line 46: [[: LIVE_DATA_2015-09: value too great for base (error token is "09")
Latest: 
Moving up a folder
Moved directory /Users/user/Desktop/WatsonErrorLogs/v448/AlloyScript/temp
End of for loop

2 个答案:

答案 0 :(得分:1)

类似于David以Linux为中心的答案,这里应该适用于OSX,FreeBSD,NetBSD等。

#!/usr/bin/env bash

max=0

# You can make this pattern more explicit if you like.
# Or you could add an `if` that verifies it and `continue`s the loop on failure.
# Or not you could just ignore the errors. :)
for fname in *.ZIP; do
  fname=${fname/.[0-9][0-9][0-9]/}    # strptime/strftime doesn't support ms...

  epoch=$(date -j -f '%Y-%m-%d_%H-%M-%S%z.ZIP' "$fname" '+%s')
  if [ $epoch -gt $max ]; then
    max=$epoch
    latest="$fname"
  fi
done

echo "Latest: $latest"

这具有使用for循环的优点,因此如果您决定扩展模式以识别此类格式,它将不会对具有特殊字符(如换行符)的文件名进行barf。

for循环为我们做的另一件事是避免子shell运行find。这样可以节省服务器上的少量资源。

一些附带条件:

答案 1 :(得分:0)

如果我理解你的问题,做你想做的事情的关键是从文件名中解析一个有效的datestring,可以用date命令找到最新的< / strong> find返回的选择中的文件。为此,您需要编写一个小脚本,因为它需要find ... -exec以外的单个命令。

注意:您没有提供完整的文件名,但我认为您的意思是2015-09-01_10-48-09.941+0000.ZIP

有很多方法可以使用小脚本来查找基于时间字符串的最新文件。使用参数扩展子字符串替换可以解决创建与date一起使用的有效日期字符串的问题。然后,每个时间戳按日期转换为seconds since epoch以进行比较:

#!/bin/bash

declare -i max=0

while read -r fname; do

    ## parese timestring from filename (assuming time.ZIP as filename)
    tmp="${fname%.ZIP}"
    t1=${tmp%_*}                    # first part (date)
    t2=${tmp#*_}                    # second part (time)
    dtstring="$t1 ${t2//-/:}"       # create date string, replace '-' with ':'
    tse=$(date -d "$dtstring" +%s)  # time (sec) since epoch
    if [ $tse -gt $max ]; then      # test for tse > max
        newest="$fname"             # save filename & update max
        max=$tse
    fi

done < <(find . -type f -name "*.ZIP" -printf "%f\n")

# just for testing
echo "max   : $max"
echo "newest: $newest"

## uncomment for actual copy
# cp "$newest" tempZIP

测试文件

$ ls -1 2015*
2015-08-31_10-48-09.941+0000.ZIP
2015-09-01_10-48-09.941+0000.ZIP

<强>输出

$ bash neweststamp.sh
max   : 1441104489
newest: 2015-09-01_10-48-09.941+0000.ZIP

在实际复​​制之前尝试一下,然后您可以调整和取消注释实际副本。

注意:参数扩展和子字符串替换存在于高级shell中,如bash。如果你必须将它限制在POSIX shell(旧的Bourne shell +),请留下评论,我们可以调整脚本(它会变得更长)

删除除最新版本之外的所有文件

继续您的评论,一旦您拥有最新的文件,您可以再次使用find删除给定目录中的所有其他文件。使用! not选项和-name(例如! -name "$newest")创建一个列表,不包括要删除的最新文件:

find /path/to/dir -type f ! -name "$newest" -exec rm '{}' \;

您也可以使用for循环:

for fname in /path/to/dir/*; do
    [ "$fname" != "$newest" ] && rm "$fname"
done

请记住:在您实际让脚本删除任何内容之前,使用echoprintf进行测试。例子:

find /path/to/dir -type f ! -name "$newest" -exec printf "rm %s\n" '{}' \;

for fname in /path/to/dir/*; do
    [ "$fname" != "$newest" ] && printf "rm %s\n" "$fname"
done

对此感到遗憾......