在BASH中使用mv命令给文件名添加时间戳

101

我是一个Linux新手,我正在使用一个简单的Bash脚本出现了问题。

我有一个程序在运行时不断往日志文件中添加内容。随着时间的推移,日志文件变得非常庞大。我想创建一个启动脚本,在每次运行程序之前重命名和移动日志文件,从而为每次程序运行创建单独的日志文件。以下是我目前拥有的内容:

pastebin

DATE=$(date +"%Y%m%d%H%M")
mv server.log logs/$DATE.log
echo program
当运行时,我看到这个:
: command not found
program

当我进入日志目录并运行dir命令时,我看到这个:

201111211437\r.log\r

发生了什么?我认为我可能遗漏了一些语法问题,但是我似乎无法弄清楚。


更新:感谢shellter在下面的评论中提供的建议,我已经发现问题是由于我在Windows的Notepad++中编辑.sh文件,然后通过ftp发送到服务器,在那里我通过ssh运行该文件。在对该文件运行dos2unix之后,它可以正常工作。

新问题:如何正确保存文件,以避免每次重新发送文件时都需要执行此修复操作?


2
\r 是回车符,检查你的 Bash 脚本,也许包含在脚本中。 - ajreal
我怎么知道呢?请附上相应的Bash脚本,可能存在不可见的空格。 - ajreal
在主贴中添加了一个pastebin链接,但那段代码片段实际上是整个脚本,我只是将启动java .jar的那一行替换为“echo program”。 - Cat5InTheCradle
不知道...看起来是正确的,你可以尝试在DATE=$(date +"%Y%m%d%H%M")后面添加一些字符串吗? - ajreal
在您的DATE=...命令上方使用set -vx来打开shell调试。然后您可以看到变量是如何被展开的。如果您在Windows上编辑此文件,然后使用编辑器的ftp客户端将脚本返回到您的unix/Linux环境中,那么很可能会添加DOS换行符到您的脚本中,即CR/LF。对于nix系统,您只需要LF。请尝试在编辑器的设置中关闭它。在您的nix系统上运行dos2unix filename也可以解决此问题。祝您好运。 - shellter
显示剩余4条评论
9个回答

109
mv server.log logs/$(date -d "today" +"%Y%m%d%H%M").log

21
date +"%Y%m%d%H%M" 如果你的bash稍有不同 - zinking
6
强调 @zinking 的观点,加号和双引号之间不能有空格。 - puk
3
我使用 date +"%Y-%m-%dT%H:%M:%S" 来生成可读的带秒的时间戳;在 Linux 上,它可以在文件名中正常工作。 - Asclepius

24

你发布的脚本几行代码看起来不错,可能是深层次的问题。

你需要找出哪一行导致了这个错误。在脚本最上面添加set -xv。这将打印出正在执行的命令和行号到STDERR。这将帮助你确定在脚本中的哪个位置发生了特定的错误。

顺便说一下,你的脚本开头有没有shebang?当我看到这样的情况时,通常认为它是与Shebang相关的问题。例如,如果你的顶部是#! /bin/bash,但是你的bash解释器位于/usr/bin/bash中,你会看到这个错误。

编辑

新问题:如何正确保存文件,以避免每次重新发送文件都必须执行此修复操作?

有两种方法:

  1. 在编辑文件时选择编辑->EOL转换->Unix格式菜单项。一旦具有正确的行结尾,Notepad++将保留它们。
  2. 为确保所有新文件都具有正确的行结尾,请转到设置->首选项菜单项,并打开首选项对话框。选择新文件/默认目录选项卡,在新文件格式下,选择Unix单选按钮。点击关闭按钮。

我会看看是否可以尝试。一旦文件被FTP到我的Linux服务器上,运行dos2unix就可以解决问题,但我正在寻找避免这个额外步骤的方法。我在开头没有shebang,那可能是关键。 - Cat5InTheCradle
3
@AgentSnazz - 啊哈!那就是问题所在。Unix shell脚本必须使用Unix换行符。Windows/MS-DOS使用回车-换行符(也称为CRLF或\r\n)标记行的末尾。Unix只使用换行符(也称为LF或\n)。如果您在Windows机器上编辑Unix文件,则必须使用能够处理正确行尾的程序编辑器(如VimNotepad++)。决不能使用记事本。这就是为什么您会在文件名中看到\r。在您的程序中,每一行的末尾都有一个看不见的\r - David W.

11

一个在bash中的单行方法如下所示。

[一些输出] >$(date "+%Y.%m.%d-%H.%M.%S").ver

将创建一个带有时间戳名称和ver扩展名的文件。通过以下工作文件列表快照到日期时间戳文件名可以展示其工作原理。

find . -type f -exec ls -la {} \; | cut -d ' ' -f 6- >$(date "+%Y.%m.%d-%H.%M.%S").ver

当然,

cat somefile.log > $(date "+%Y.%m.%d-%H.%M.%S").ver

或者更简单的是

ls > $(date "+%Y.%m.%d-%H.%M.%S").ver


9

我使用这个命令来简单旋转一个文件:

mv output.log `date +%F`-output.log

我本地文件夹里有一个 2019-09-25-output.log 文件。


5

嗯,这并不是对你问题的直接回答,但在GNU/Linux中有一个工具可以定期轮换日志文件,将旧的压缩并保留到一定数量的限制。它就是logrotate


我会看一下,我喜欢我的方法,因为它可以将每次程序运行都很好地包装在自己的日志文件中。 - Cat5InTheCradle

5

首先,感谢以上的回答!它们帮助我找到了解决方案。

我在我的 .bashrc 文件中添加了这个别名:

alias now='date +%Y-%m-%d-%H.%M.%S'

现在,当我想给一个文件(例如构建日志)加上时间戳时,可以这样做:
mvn clean install | tee build-$(now).log

我得到了一个文件名,如下:

build-2021-02-04-03.12.12.log


1
你可以在记事本中编写脚本,但要确保使用以下命令进行转换:$ sed -i 's/\r$//' yourscripthere。我在使用cygwin时经常使用它,它很有效。希望这能帮到你。

0

只需使用小写字母(表示年-月-日)和大写字母(表示时-分-秒),例如:

TIMESTAMP=$(date +"%**Y**.%m.%d-%H.%M.%S") get **2023**.04.13-07.56.05

或者

TIMESTAMP=$(date +"%**y**.%m.%d-%H.%M.%S") get **23**.04.13-08.01.03

0
$mv OldFileName NewFileName$(date +%Y%m%d%H%M%S)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接