【问题标题】:How do I tar files and put them in a list with gitbash我如何 tar 文件并使用 gitbash 将它们放入列表中
【发布时间】:2020-11-30 04:14:49
【问题描述】:

我正在使用 Git bash,并希望使用 git Bash 中的“tar”功能归档我的文件。

如您所见,这些文件的名称中有日期,我想将所有日期压缩到单独的 tar 文件中。 在这种情况下,结果将是我有 2 个具有 2 个不同日期的 tar 文件。

我的想法是用find iname "jo* | \d\d\d\d\d\d | sort | tar -czvf testarchive.zip ~/test/targetfolder“找到”这些文件中的 6 位数字,然后将它们 tar。但是,我必须将第一个找到的日期放入列表中,将它们 tar 直到日期更改,然后将第二个日期文件放入列表中,依此类推...

由于我没有 bash 和脚本编写经验,我不知道如何解决这个问题。我会很高兴得到帮助。我还没有在互联网上找到解决方案..

附:我不确定 git bash 是 Linux/Unix 还是其他脚本语言,还是只是 Git bash,如果我没有满足所有要求,请见谅。

【问题讨论】:

  • Bash 无处不在。它通常与 Windows 上的版本控制系统 Git 捆绑在一起,因为 Windows 上的本机命令 shell 很糟糕和/或在 Windows 版本之间不兼容,但它本身不是 Git 的一部分或依赖于 Git。
  • .zip 扩展名通常仅用于 PKzip 和相关档案,其格式与 tar 档案完全不同。 gzip(不是 zip!)压缩 tar 文件的习惯扩展名是 .tar.gz,或在文件扩展名只有三个字母可用的遗留系统上为 .tgz。如果您想创建 .zip 档案,请查找 zip 实用程序。

标签: linux bash unix git-bash


【解决方案1】:

乍一看,我会构建一个由唯一日期组成的关联数组,然后是 tar 每个匹配的集合。

$: echo jo* # I made some similar local files
jo02042018ab jo02042018cd jo10112018ab jo10112018cd jo10112018ef

文件名不准确,但足以说明问题。

$: declare -A dateLst # create an *associative* array, keys are dates

关联数组使用字符串作为索引(即使它们是数字)。

$: for f in jo[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]?? # for each file
>  do dateLst["${f//[^0-9]/}"]=1                         # assert date as a key
>  done

dateLst[somekey]=1dateLst 中创建一个唯一的somekey
${f//[^0-9]/} 从文件名中删除所有非数字,只留下日期。 (即使它们实际上具有 .txt 文件扩展名,这也可能会正常工作,尽管您需要在 for 语句中编辑 glob。)
因此,dateLst["${f//[^0-9]/}"]=1 将文件中的日期设置为查找表中的键。如果它已经存在,它只是重新设置它。

我们现在有一个可用于创建 tarball 的唯一日期表。

$: for t in "${!dateLst[@]}"; do echo tar -cvzf $t.tgz jo$t*; done
tar -cvzf 10112018.tgz jo10112018ab jo10112018cd jo10112018ef
tar -cvzf 02042018.tgz jo02042018ab jo02042018cd

${!dateLst[@]} 是表中的键,所以这会循环不同的日期和echos tar 命令来创建每个 tarball。 jo$t* 列出要包含在该存档中的所有匹配文件。删除echo 以执行命令。

【讨论】:

  • 我一步一步尝试了这个。但它不起作用。它告诉我“tar: jo090909090909*: Cannont stat: no such file or directory
  • 必须在包含源文件的目录中运行。
【解决方案2】:

也许您正在寻找类似的东西?

for pat in jo[0-9][0-9][0-9][0-9][0-9][0-9]*; do
    tail=${pat#jo[0-9][0-9][0-9][0-9][0-9][0-9]}
    head=${pat%"$tail"}
    date=${head#jo}
    # If this tarball exists, skip
    if [ -e "$date.tar.gz" ]; then
        continue
    fi
    # Else, tar this date
    tar czvf "$date.tar.gz" "jo$date"*
done

目前尚不清楚您希望~/test/targetfolder 将在何处或如何使用。如果那是文件所在的位置,那么在运行它之前可能只是 cd 那里。如果您希望在此处创建 tar 文件,请将其放在上述所有位置的 "$date.tar.gz" 之前。

参数扩展${variable#pattern}${variable%pattern} 产生$variable 的值,分别删除pattern 上的任何前缀或后缀匹配。

【讨论】:

  • 谢谢。这行得通。而且我也成功声明了我的目标文件夹。但我想知道这些线路在做什么?您写道,他们正在产生 $variable 的值,但我不太了解它。 1. 我以为“#”是用来注释的,你把它放在第 2 行 pat 2 之后。“pat%”在第 3 行返回什么? 3. if 子句中的“-e”在做什么?这是否意味着存在?
  • 它们在${...} 中很特别。举个简单的例子,echo "${HOME#/}" 打印您的主目录,并删除了第一个 /(前缀匹配文字斜杠,变量通常以斜杠开头,因此前缀匹配并被删除)。是的,[-e 选项检查文件是否存在。如果您看不懂手册,不妨试试explainshell.com
  • 我在任何地方都找不到,“%”代表什么?我知道“pat#jo”的意思是“pat without jo*”但是“pat%tail”是什么意思?
  • 如果你有一个变量$pat 的值为foobarbaz,那么${pat#foo} 产生barbaz$(pat%baz} 产生foobar(当然${pat#other} 仍然产生@987654343 @ 因为other 不匹配值的开头,所以什么都没有被剥离)。这称为“参数扩展”;有关详细信息,请参阅the reference manual
  • 删除前缀,然后从后缀中删除结果会产生开头被删除的部分;所以${pat%"$tail"} 剪掉了我们刚刚提取到tail 中的东西,剩下的就是我们从尾部剪掉的前缀。我们走这条弯路是因为我们可以预测前缀的长度,但不能预测后缀的长度;如果该模式允许更复杂的操作,比如正则表达式,这可能会更简洁(但总体上可能更难理解和维护)。
猜你喜欢
  • 2022-12-15
  • 2017-02-19
  • 1970-01-01
  • 1970-01-01
  • 2011-08-19
  • 1970-01-01
  • 2017-11-21
  • 2023-04-11
  • 1970-01-01
相关资源
最近更新 更多