【问题标题】:Loop over different directories and change of file name循环遍历不同的目录并更改文件名
【发布时间】:2020-12-11 13:50:22
【问题描述】:

我有以下主题文件夹结构:

./sub-CC0006/func
..
./sub-CC0199/func

在 func 文件夹中,我有一个名为 sub-CC0006_ses-core2p2_task-loi3_run-01_events.tsv 的文件。当我尝试将以下代码放入循环时,它不起作用。 (我尝试先循环到每个主题目录,然后根据不同的主题编号更改 .tsv 文件名。)

awk -F"\t" -v OFS="\t" '{
       for (i=1;i<=NF;i++) {
         if ($i == "NaN") $i="n/a"
       }
       print $0
 }' sub-CC0006_ses-core2p2_task-loi3_run-01_events.tsv > sub-CC0006_ses-core2p2_task-loi3_run-01_events_new.tsv &&
mv sub-CC0006_ses-core2p2_task-loi3_run-01_events_new.tsv sub-CC0006_ses-core2p2_task-loi3_run-01_events.tsv

这是我试图操作的文件之一的摘录:

onset response_time
9 NaN
12 1.4

【问题讨论】:

  • 您可以为某些上下文添加 tsv 文件的摘录吗?
  • 我刚刚编辑了我的帖子并将其包含在内,谢谢您的建议。更多的上下文。我只是想将所有这些文件中的 NaN 更改为 n/a。但是,我遇到了循环问题。
  • 你能发布文件中的原始文本而不是图像吗?
  • 如果我正确理解了这个问题,文件的内容在很大程度上与问题所问的问题无关,即管理文件的名称,以便将awk 的输出保存在某处然后将输出移动/复制到原始文件上。 awk 脚本将字段中所有出现的NaN 映射到n/a,仅此而已。那里没有兴奋。

标签: bash loops


【解决方案1】:

用文件的编辑版本覆盖文件的基本技术使用通用临时文件名作为中间文件。

我假设在sub-CC0199 目录中,func 子目录将包含sub-CC01999_ses-core2p2_task-loi3_run-01_events.tsv,并且该目录中的任何其他文件都将被忽略,对于其他目录也是如此。如果您只想处理每个主题的每个 func 子目录中的所有文件(或所有 *.tsv 文件或其他模式匹配),脚本会变得更简单。

tmpfile=$(mktemp "map.XXXXXX")
trap "rm -f $tmpfile; exit 1" 0 1 2 3 13 15

suffix="_ses-core2p2_task-loi3_run-01_events.tsv"

for directory in sub-CC0???
do
    file="$directory/func/$directory$suffix"
    if [ -f "$file" ]
    then
        awk '…' "$file" > "$tmpfile" &&
        mv "$tmpfile" "$file"
    fi
done

rm -f "$tmpfile"   # Remove the temporary
trap 0             # Cancel the 'exit' trap; the script exits with status 0    

如果您担心保留原始文件上的链接(或所有权或权限),或者原始文件可能是您想要保留的符号链接,您可以使用cp "$tmpfile" "$file"; rm -f "$tmpfile" 而不是mv。不过它会稍微慢一些——但除非文件很大,否则可能不会慢得多。

您可以在循环中生成临时文件名;如果您担心恶意行为者,这样做可能会稍微安全一些。该文件在mktemp 创建时是新文件(以前不存在),但在您移动它之后,恶意人员可以创建自己的符号链接到敏感位置,因此脚本可能会意外损坏其他文件。 (您也可以在不删除临时文件的情况下将临时文件复制到原始文件上,因此每个.tsv 文件都使用相同的文件 - 选项很多。)不过,您可能不在一个充满敌意的环境中工作。

trap 列表用于“EXIT”(0) 和信号 1 (SIGHUP)、2 (SIGINT)、3 (SIGQUIT)、13 (SIGPIPE) 和 15 (SIGTERM)。当只有数字有效时,我学会了编写脚本——而且它们很紧凑。如果您想更现代一点,可以列出信号和条件的简称:

trap "rm -f $tmpfile; exit 1" EXIT HUP INT QUIT PIPE TERM
…
trap EXIT

或(取消多个陷阱,尽管在脚本即将退出时没有必要):

trap - EXIT HUP INT QUIT PIPE TERM

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-20
    • 2020-11-05
    • 1970-01-01
    • 2013-12-03
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多