重命名任何深层子文件夹(如父文件夹)中的文件,然后移至中央文件夹

重命名任何深层子文件夹(如父文件夹)中的文件,然后移至中央文件夹

我遇到一个问题,我需要在父文件夹之后重命名某些文件,然后将它们移动到中央文件夹。有没有办法做到这一点?我想在 Synology NAS 上运行它。

Root
 |-Subf1
 |  |-File.txt
 |  |-File.doc
 |  |-Subf1subf1
 |  |  |-File.xml
 |  |  |-File.xls
 |  |-Subf1subf2
 |  |  |-File.pptx
 |  |  |-File.docx
 |
 |-Subf2
 |  |-File.txt
 |  |-File.doc
 |  |-Subf2subf1
 |  |  |-File.xml
 |  |  |-File.xls

结果应该是:

Root
 |-Subf1
 |  |-Subf1.txt
 |  |-Subf1.doc
 |  |-Subf1.xml
 |  |-Subf1.xls
 |  |-Subf1.pptx
 |  |-Subf1.docx
 |
 |-Subf2
 |  |-Subf2.txt
 |  |-Subf2.doc
 |  |-Subf2.xml
 |  |-Subf2.xls

覆盖文件没有问题,因为它们都有不同的扩展名。

答案1

#! /bin/bash

shopt -s globstar  #enabled for '**' to match all files &directories recursively
#shopt -s dotglob  #uncomment to enable to match on hidden files/directories too

cd /path/to/directory/Root
for pathname in ./**/*; do
    [[ -f "$pathname" ]] && echo mv -v -- "$pathname" "${pathname%%/*}/${pathname%%/*}.${pathname##*.}";
done

##then remove remained empty directories
for pathname in ./**/*; do
    [[ -d "$pathname" && -z "$(ls -A -- "$pathname")" ]] && rm -r -- "$pathname";
done
  • [[ -f "$pathname" ]]检查是否$pathname是一个f文件
  • ${pathname%%/*}: 使用shell 参数扩展,从参数中删除最长的后缀pathname。剪切第一个斜线字符之前的所有内容/
  • ${pathname##*.}":相同,但是这会从参数中删除最长的前缀pathname;剪切所有内容直到最后一个点.字符。
  • [[ -d "$pathname" ]]检查是否$pathname是一个d目录
  • ... && -z "$(ls -A -- "$pathname")"然后检查基名是否pathname 这是一个目录,是否为空

echo当您对结果满意时删除。

答案2

POSIXly:

cd Root &&
  LC_ALL=C find . \
    -name '.?*' -prune -o \
      -path './*/*/*' \
      -prune \
      -name '*.*' \
      -type f \
      -exec sh -c '
        ret=0
        for file do
          ext=${file##*.}
          sub=${file%/*/*}
          subname=${sub##*/}
          echo mv -i "$file" "$sub/$subname.$ext" || ret=$?
        done
        exit "$ret"' {} +

echo(如果高兴就删除)

之后可以使用以下命令删除空目录:

find . -depth -type d -exec rmdir {} + 2> /dev/null

或者如果您find支持非标准-empty-delete

find . -type d -empty -delete

-delete暗示-depth)。

相关内容