for 循环将目录名称添加到文件名前面

for 循环将目录名称添加到文件名前面

我知道这个主题已经被讨论过(在这里和其他地方),但我请求你宽容,因为我正在尝试通过 bash 脚本艺术找到我的方法;

我需要解决以下问题

鉴于我有:

目录1

  • 文件1
  • 文件2
  • 等等...

目录2

  • 文件1
  • 文件2
  • 等等...

我想重命名文件以便

目录1

  • 目录1_文件1
  • 目录1_文件2
  • dir1_等等...

目录2

  • 目录2_文件1
  • 目录2_文件2
  • dir2_等等...

到目前为止,我已经设法制定出以下“探索性”bash 脚本

for d in `ls -d */`
 do
   #echo "$d"
   pre="${d:0:-1}"
   #echo "$pre"
   #cd "${d}"
   pushd "${d}"
    for f in *.jp2
     do
        #echo "${f}"
        echo "${pre}_${f}"
     done
   #cd - 
   #popd    
 done

除了错误消息之外,它似乎工作(相当)正常

line 9: pushd: dir2/: No such file or directory

其中 dir2 是 for 循环扫描的最后一个目录的名称...

有什么帮助吗?我缺少什么?

答案1

而不是尝试cd来回进入目录(popd并且pushd主要用于交互使用):

#!/bin/sh

for name in */*; do
    [ ! -f "$name" ] && continue

    dir="$( basename "$( dirname "$name" )" )"
    newname="$dir/${dir}_${name##*/}"

    if [ ! -e "$newname" ]; then
        echo mv "$name" "$newname"
    fi
done

这将迭代当前目录中所有目录中的所有名称。它将跳过非文件并将目录基本名称(没有路径的目录名称)提取到dir.然后,它使用(可以替换为)中的路径名的基本名称部分$newname为该文件构造一个新的文件名。$dir$name${name##*/}$( basename "$name" )

如果尚未使用新名称,则文件将被重命名。

echo一旦您确认它应该做正确的事情,请删除它以实际重命名文件。


要在另一个目录中执行一组操作然后返回,请使用

( cd dir
  action
  action 
  action )

更改的目录不会影响( ... ).


也可以看看:为什么*不*解析`ls`?

答案2

你说“dir2是for循环扫描的最后一个目录的名称”,但它实际上是第二最后,不是吗?它失败了,因为你已经popd注释掉了。在第一次循环迭代结束时,您仍然处于“in”状态dir1,因此您的尝试pushd dir2实际上是在寻找dir1/dir2;即,dir2在 内dir1

如果您有七个目录,那么最后六个目录将会失败。

您提出了这样的担忧:“取消注释 popd 会导致其他不需要的后果,...即,如果 for 循环迭代的目录(同一级别)中存在文件(不是目录),情况会怎样”。出色地,

  • 这种逻辑就像是在说:“如果我除了穿左鞋之外还穿右鞋,那么我的枪就多了一个目标,所以我更有可能用右脚开枪自杀。”这毫无意义。只穿pushd而不遵循popd(尤其是循环)比只穿一只鞋要错误得多。
  • 由于您使用的是*/,因此您只会获得目录。
    • 但 Kusalananda 是对的:你应该使用for d in */而不是for d in `ls -d */`⁠.
  • 更好的是,你可以做类似的事情

    for d in *
     do
        if [ -d "$d" ]
        then
            pushd "$d"
            for f in *.jp2
             do
             done
            popd    
        fi
     done
    

    或者

    for d in *
     do
        if pushd "$d" 2> /dev/null
        then
            for f in *.jp2
             do
             done
            popd    
        fi
     done
    

    所以你不要尝试将非目录视为目录。

相关内容