【问题标题】:I need to rename files based on a matching string in another file [closed]我需要根据另一个文件中的匹配字符串重命名文件[关闭]
【发布时间】:2019-02-12 11:31:38
【问题描述】:

我有一个这样的文件列表

186866-Total-Respondents.csv
343764-Total-Respondents.csv
415612-Total-Respondents.csv
761967-Total-Respondents.csv

我想通过将上面的第一个数字字符串与同一目录中名为 data.txt 的文件中的相同数字字符串匹配来重命名它们。

data.txt的内容如下

2018-09-Client-1-761967-Brand-1-Total-Respondents
2018-09-Client-1-415612-Brand-2-Two-Total-Respondents
2018-09-Client-1-186866-Brand-Three-Total-Respondents
2018-09-Client-2-343764-Brand1-Total-Respondents
2018-09-Client-3-347654-No-Name-Brand-Total-Respondents
2018-09-Client-3-109321-House-Brand-Total-Respondents

最终结果是上面4个匹配的文件会被重命名为

2018-09-Client-1-186866-Brand-Three-Total-Respondents.csv
2018-09-Client-2-343764-Brand1-Total-Respondents.csv
2018-09-Client-1-415612-Brand-2-Two-Total-Respondents.csv
2018-09-Client-1-761967-Brand-1-Total-Respondents.csv

我找到了一个使用 sed 和正则表达式的 similar question,但我无法编辑正则表达式以成功重命名。

我猜 sed 或 awk 在这里会很好用吗?

【问题讨论】:

  • 欢迎来到 SO。 Stack Overflow 是一个面向专业和狂热程序员的问答网站。目标是您将一些自己的代码添加到您的问题中,以至少显示您为解决这个问题所做的研究工作。

标签: bash file awk sed rename


【解决方案1】:
# you have list of files
touch 186866-Total-Respondents.csv 343764-Total-Respondents.csv  415612-Total-Respondents.csv 761967-Total-Respondents.csv

# and data.txt
cat >data.txt <<EOF
2018-09-Client-1-761967-Brand-1-Total-Respondents
2018-09-Client-1-415612-Brand-2-Two-Total-Respondents
2018-09-Client-1-186866-Brand-Three-Total-Respondents
2018-09-Client-2-343764-Brand1-Total-Respondents
2018-09-Client-3-347654-No-Name-Brand-Total-Respondents
2018-09-Client-3-109321-House-Brand-Total-Respondents
EOF

# and you need to join them on the first field from list and the 5th field from data
# got a little `while read` there, cause I got no good idea how to replace 4th occurence of char with a tab or space
# also I needed to add `.csv` suffix to the data.txt, but I could have just `sed 's/$/.csv/'
# xargs then eats every two arguments and runs mv
join -11 -25 -t- <(printf "%s\n" *.csv | sort) <(<data.txt sort -t- -k5) \
| while IFS=- read -r a b c r; do echo "$a-$b-$c" "$r".csv; done \
| xargs -n2 mv

脚本将执行:

mv 186866-Total-Respondents.csv 2018-09-Client-1-Brand-Three-Total-Respondents.csv
mv 343764-Total-Respondents.csv 2018-09-Client-2-Brand1-Total-Respondents.csv
mv 415612-Total-Respondents.csv 2018-09-Client-1-Brand-2-Two-Total-Respondents.csv
mv 761967-Total-Respondents.csv 2018-09-Client-1-Brand-1-Total-Respondents.csv

【讨论】:

  • 感谢您的帮助...当 4 个文件在一个目录中时,cat &gt;list &lt;&lt;EOF 行如何工作?我可以使用ls *.csv 之类的东西吗?
  • 您可以使用printf "%s\n" *.csv find . -type f -maxdepth 1 -name '*.csv' -printf '%P\n'。永远不要在脚本中使用ls,它是为了漂亮的终端打印,而不是批处理脚本。我编辑了答案。
  • 好的,这绝对有帮助,谢谢...我删除了 touch 行,因为文件已经在目录中,data.txt 也是如此,但是以 join 开头的 3 行看起来不错...我只需要进行更多测试...
  • 我可以看到您正在按 data.txt 中的第 5 列进行排序,但是如果 ID 在第 4 列或第 5 列中,它将如何工作?这种情况也能涵盖吗?
  • sort -t- -k1sort 不一样吗?
【解决方案2】:

如果你有这两个文件,并且你想用awk 来做,那么这个工作:

awk -F "-" '(NR==FNR){a[$1]=$0;next}
            ($5 in a){system("mv "a[$5]" "$0".csv)}' file1 file2

file1 是文件列表,file2 是数据文件。

另一种方法是,如果您只有数据文件,

#!/usr/bin/env bash
while read -r line; do          # read a full line from data.txt
   IFS="-" read -r a a a a value a <<<"${line}"
   old="${value}-Total-Respondents.csv";  # build old name
   [[ -e "${old}" ]] && mv "${old}" "${line}.csv" # move if file exists
done < data.txt

【讨论】:

  • 嘿,很好 :) 不过要继续吹毛求疵……我不会指望所有文件都遵循value-Total-Respondents.csv 的事实。我可能会使用f=("$value"-*.csv); ((${#f[@]}==1)) &amp;&amp; mv "$f" ...
  • @PesaThe 可能是真的,但这不是 OP 的想法。也许他只想移动${value}-Total-Respondents.csv,但同一目录有${value}-Partial-Respondents.csv。这样脚本就会失败。
猜你喜欢
  • 2015-04-04
  • 1970-01-01
  • 2023-03-16
  • 2020-02-25
  • 2016-11-10
  • 1970-01-01
  • 2014-07-27
  • 2020-10-08
  • 2022-09-25
相关资源
最近更新 更多