始终备份

始终备份

我有大量文件(数万个)需要从 /dir1 复制到 /dir2,但文件的名称必须按如下方式更改:

旧名称--->新名字

文件名.txt ---> bob_文件名_1253.txt

其中 bob 是拥有该文件的 uid,1253 是上次修改的时间。

我目前正在使用一个 python 脚本实现这一点,该脚本循环遍历每个文件,然后将其 cp 到新目的地,并通过字符串切片创建新的文件名。

然而,这需要花费大量的时间。有没有更干净、更快捷的方法来实现这一点?

提前致谢!

答案1

假设你从一个空文件夹开始,这样你就可以在不发生冲突的情况dir2下将文件从复制dir1dir2然后重命名它们,我会尝试这样的事情:

printf '%s\0' dir1/*.txt | xargs -r0 cp -np -t dir2/

执行复制,然后

cd dir2/

printf '%s\0' *.txt | xargs -r0 rename -n -- '
  $_ = join "_", ( getpwuid( (stat $_)[4] ) )[0], $_, (stat $_)[9]
'

重命名(对建议的更改满意后,-n从命令中删除)。rename


虽然它最常用于简单的s/pattern/replacement/名称更改,但 Ubuntu 当前版本中提供的基于 Perl 的rename命令实际上可以根据几乎任意的 Perl 表达式重命名文件。

在这种情况下,我们可以使用 Perl 的内置功能stat来获取数字 UID 和 mtime,然后使用getpwuid将 UID 转换为用户名。(stat $_)[9]是以纪元秒为单位的修改时间 (mtime) - 如果需要其他格式,您可以使用POSIX::strftime或其他几个时间操作模块之一。

答案2

*.txt文件从目录复制dir1/dir2/目录并重命名:

$ ls -l
共 8
drwxr-xr-x 2 用户 用户 4096 лют 19 01:06 dir1
drwxr-xr-x 2 用户 用户 4096 лют 19 01:08 dir2

$ ls dir1
名称1.txt 名称2.txt 名称3.txt
$ 表示 ./dir1/* 中的文件路径;
    执行用户名=$(stat -c '%U' $filepath) &&
       文件日期=$(stat -c '%Y' $文件路径) &&
       newpartname='dir2/'$n'_'“${filepath//'./dir1/'}”&&
       cp $filepath "${newpartname//'.txt'}"_$filedate.txt;
    完毕
ls 目录2/
用户名称1_1582067151.txt 用户名称2_1582067158.txt 用户名称3_1582067165.txt

您说重命名需要花费很多时间。但是您的所有文件的大小是多少?您知道复制所有文件需要的时间吗?

答案3

以下脚本应该可以完成工作。尝试一下,当你对结果满意时,删除#前面的注释cp -p "$oldpath""$f9" "$newpath""$new"以执行实际工作。

该脚本将在您的主目录中创建一个名为的文件ls_file.txt。此文件用于存储ls -l "$oldpath"命令的输出,脚本在执行期间需要从中读取。脚本执行完成后,该ls_file.txt文件不再需要,您可以将其删除。

始终备份

要创建和使用脚本文件,请按照以下步骤操作:

  1. 通过在终端中运行以下命令,在主目录中创建并编辑脚本文件:

    nano ~/my_script.sh

  2. 将以下代码复制并粘贴到编辑器中,并将其更改/full/path/to/old/directory/为目录的完整路径/dir1和目录/full/path/to/new/directory/的完整路径/dir2

#!/bin/bash

oldpath="/full/path/to/old/directory/"
newpath="/full/path/to/new/directory/"

ls -l "$oldpath" > "ls_file.txt"

while read f1 f2 f3 f4 f5 f6 f7 f8 f9
                do
                        mod="${f6}${f7}${f8}"
                        mod2=$(echo "$mod" | tr -d ' :')
                        name="${f9%.*}"
                        ext="${f9##*.}"
                        new="$f3""_""$name""_""$mod2"".""$ext"
                        echo "$f9"" ---> Will be renamed ---> ""$new"
                        echo "----------------------------"
#                       cp -p "$oldpath""$f9" "$newpath""$new"
                done < "ls_file.txt"
  1. 保存脚本文件并按Ctrl+X然后按退出编辑器Y

  2. 通过在终端中运行以下命令使脚本文件可执行:

    chmod +x ~/my_script.sh

  3. 通过在终端中运行以下命令来运行脚本:

    bash ~/my_script.sh

完毕


怎么运行的?

dir1/从我的主目录在包含一个文件file.txt和一个dir2/为空的测试目录上运行脚本,同时指定oldpath="/home/raffa/test/dir1/"newpath="/home/raffa/test/dir2/",以下过程是脚本如何工作的示例:

  1. 该命令ls -l /home/raffa/test/dir1/被执行并且输出被写入一个名为的文件ls_file.txt,该文件将包含文件的属性和名称(在dir1/本例中为一个文件),file.txt如下所示:
-rw-r--r-- 1 raffa raffa 0 Jan 25 19:49 file.txt
  • -rw-r--r--是文件模式。
  • 1是链接的数量。
  • 第一个raffa是主人的名字。
  • 第二个raffa是团体的名称。
  • 0是文件大小。
  • Jan 25 19:49 (三个字段)是最后修改的日期和时间。
  • file.txt是文件的名称。

. 2. 脚本会逐行读取 的内容dir1/并将ls_file.txt每行拆分为字段(共九个),并将每个字段的值赋给一个变量f1 f2 f3 f4 f5 f6 f7 f8 f9

  1. mod="${f6}${f7}${f8}"将把存储在变量中的最后修改日期和时间分配f6 f7 f8给变量mod,因此它将包含如下值:
Jan2519:49
  1. mod2=$(echo "$mod" | tr -d ' :')将获取变量的值$mod,删除任何空格和冒号:并将其分配给变量mod2,因此它将包含如下值:
Jan251949
  1. name="${f9%.*}"将会把不带扩展名的文件名分配给变量name,因此它将包含如下值:
file
  1. ext="${f9##*.}"将会把不带名称的文件扩展名分配给变量ext,因此它将包含如下值:
txt
  1. new="$f3""_""$name""_""$mod2"".""$ext"将把新文件名格式化为owner_name_lastmodified.extension并将其分配给变量new,因此它将包含如下值:
raffa_file_Jan251949.txt
  1. cp -p "$oldpath""$f9" "$newpath""$new"将会把原始文件file.txt从复制dir1/dir2/并将其重命名为raffa_file_Jan251949.txt,并尝试在此过程中保留文件的原始属性,因此它将像这样执行:
cp -p /home/raffa/test/dir1/file.txt /home/raffa/test/dir2/raffa_file_Jan251949.txt

该过程将针对具有任何扩展名的所有文件重复进行dir1/


另一种时间格式:

如果您希望最后修改日期和时间格式如下,20200125133815其中2020是年份 ,01是月份 ,25是日期 ,13是 24 格式的小时 ,38是分钟 ,15是秒 ,那么您复制的文件名将如下所示raffa_file_20200125133815.txt,请使用以下代码替换上面的脚本代码:

#!/bin/bash

oldpath="/full/path/to/old/directory/"
newpath="/full/path/to/new/directory/"


ls -l --time-style="+%Y%m%d%H%M%S" "$oldpath" > "ls_file.txt"

while read f1 f2 f3 f4 f5 f6 f7
                do
                        mod="${f6}"
                        name="${f7%.*}"
                        ext="${f7##*.}"
                        new="$f3""_""$name""_""$mod"".""$ext"
                        echo "$f7"" ---> Will be renamed ---> ""$new"
                        echo "----------------------------"
#                       cp -p "$oldpath""$f7" "$newpath""$new"
                done < "ls_file.txt"

注意:

在某些情况下解析输出ls也许可以更好地避免。

相关内容