Shell Bash脚本从子目录中移动最新的特定文件类型 从当前目录中搜索所有子目录 仅针对特定的文件扩展名类型

Shell Bash脚本从子目录中移动最新的特定文件类型 从当前目录中搜索所有子目录 仅针对特定的文件扩展名类型,shell,Shell,仅将标题中带有时间戳的最新文件复制到另一个目录 找到-mindepth 2-名称“*.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 currentDirec

仅将标题中带有时间戳的最新文件复制到另一个目录

找到-mindepth 2-名称“*.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

如果我理解您的问题,那么执行您想要执行的操作的关键是从文件名中解析有效的
日期字符串
,该文件名可与
date
命令一起使用,以在
find
返回的选择中查找最新的文件。要做到这一点,您将需要编写一个小脚本,因为它需要多个可由
find-exec

注意:您没有提供完整的文件名,但我假设您的意思是
2015-09-01\u 10-48-09.941+0000.ZIP

有许多方法可以使用小脚本根据时间字符串查找最新文件。使用参数展开子字符串替换是处理创建有效日期字符串以与
日期
一起使用的方法。然后将每个时间戳按日期转换为自历元起的
,以便进行比较:

#!/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
输出

$ bash neweststamp.sh
max   : 1441104489
newest: 2015-09-01_10-48-09.941+0000.ZIP
在实际复制之前尝试一下,然后可以调整并取消对实际副本的注释

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

删除除最新文件以外的所有文件

$ bash neweststamp.sh
max   : 1441104489
newest: 2015-09-01_10-48-09.941+0000.ZIP
继续您的评论,一旦您有了最新的文件,您可以再次使用
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
记住:在实际让脚本删除任何内容之前,先使用
echo
printf
进行测试。示例:

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


这样就少了遗憾…

与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
循环,因此在您决定扩展模式以识别此类格式时,不会在文件名上出现诸如换行符之类的特殊字符

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

一些但书:

  • 如果您需要精度小于一秒,则此解决方案将需要额外调整
  • 这是……)
所以。。这不是bash脚本。bash中没有内置
find
命令。您是否正在寻找一种避免使用
find
的方法?我不介意使用find。这似乎使迭代和使用find逻辑变得困难。我只想在每个子目录中选择最新的ZIP文件。我不知道如何对目录和子目录中的文件进行迭代和比较。需要明确的是,此解决方案在大多数Linux发行版中都能工作,但在OSX、FreeBSD和其他BSD中会失败,因为
日期
命令中有
-d
选项。在BSD派生的Unice中,可以使用
-f
选项指定要转换的日期的输入格式。OP没有提到他的操作系统,所以重要的是要么让答案可移植,要么注意它的局限性。同意。感谢您收看
date-f
。啊!我想拍苹果的原因有很多。这是一个。为什么在Linux、FreeBSD、OSX和其他系统之间,我们不能都只获得一些基础知识,比如<代码>阅读<代码>,<代码>日期<代码>,等等。。。我不想再做同样的事了
:p
。看看戈蒂的回答,看起来他已经为OSX敲定了。谢谢。我将尝试改进ghoti所做的,看看我能想出什么。我仍然不知道如何删除每个子目录中除最新文件以外的所有文件。我在我的答案末尾为您添加了一个删除除最新文件以外的所有文件的完整示例。
#!/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"