根据Linux中的文件数重命名目录

时间:2020-11-29 10:32:35

I have the following layout:

我有以下布局:

  • d1
    • f1
    • f2
    • f3
  • d1 f1 f2 f3

  • d2
    • f4
    • f5
  • d2 f4 f5

  • d3
    • f6
    • f7
    • f8
    • d4
      • f9
  • d3 f6 f7 f8 d4 f9

What I want to do is rename the root directories to contain the number of (recursive) files contained within. The format isn't super important as long as it's not too long. I want to be able to run this script as a cron every hour or so to update the directory names, so after the first run it will look like this:

我想要做的是重命名根目录以包含其中包含的(递归)文件的数量。只要不太长,格式就不是非常重要。我希望能够每小时左右以cron的身份运行此脚本来更新目录名称,因此在第一次运行后它将如下所示:

  • 3-d1
    • f1
    • f2
    • f3
  • 3-d1 f1 f2 f3

  • 2-d2
    • f4
    • f5
  • 2-d2 f4 f5

  • 4-d3
    • f6
    • f7
    • f8
    • d4
      • f9
  • 4-d3 f6 f7 f8 d4 f9

Then after the second run, maybe a few more files will have been added and removed, and now it looks like this:

然后在第二次运行之后,可能会添加和删除更多文件,现在它看起来像这样:

  • 1-d1
    • f1
  • 4-d2
    • f2
    • f3
    • f4
    • f5
  • 4-d2 f2 f3 f4 f5

  • 10-d3
    • f6
    • f7
    • f8
    • d4
      • f9
      • f10
      • f11
      • f12
      • f13
      • f14
      • f15
    • d4 f9 f10 f11 f12 f13 f14 f15

  • 10-d3 f6 f7 f8 d4 f9 f10 f11 f12 f13 f14 f15

I have the following bash script so far, but I can't figure out how to do the regex replacement on the filename

到目前为止,我有以下bash脚本,但我无法弄清楚如何在文件名上进行正则表达式替换

#!/bin/bash

TARGETPATH=/home/pritchea/test
for CURDIR in `ls -l $TARGETPATH`
do
  if [ -d $TARGETPATH/$CURDIR ]; then
    echo "$CURDIR is a directory"
    FILECOUNT=`find $TARGETPATH/$CURDIR -type f | wc -l`
    echo " and there are $FILECOUNT file(s)";
  fi
done

2 个解决方案

#1


3  

before

.
├── d1
│   ├── f1
│   ├── f2
│   └── f3
├── d2
│   ├── f4
│   └── f5
└── d3
    ├── d4
    │   └── f9
    ├── f6
    ├── f7
    └── f8

run the command at top level dir

cd /home/pritchea/test

for i in *
do
    [[ -d $i ]] || continue
    n=${i#*-}
    c=$(find "$i" -type f -printf x | wc -c)
    [[ $i == $c-$n ]] && continue
    mv -f "$i" "$c-$n"
done

after

.
├── 2-d2
│   ├── f4
│   └── f5
├── 3-d1
│   ├── f1
│   ├── f2
│   └── f3
└── 4-d3
    ├── d4
    │   └── f9
    ├── f6
    ├── f7
    └── f8

#2


0  

This is the way I did it. I loop over all the directories in $TARGETPATH, using ls -l to check how many files that are not directories exist in each $CURDIR. Note: this might not be the best method (find -f might give better results; I haven't checked with symlinks etc).

这就是我做的方式。我遍历$ TARGETPATH中的所有目录,使用ls -l检查每个$ CURDIR中有多少个不是目录的文件。注意:这可能不是最好的方法(查找-f可能会给出更好的结果;我没有检查过符号链接等)。

Because wc -l tends to give output that looks similar to [ 1], rather than [1], I strip the whitespace using sed.

因为wc -l倾向于给出类似于[1]而不是[1]的输出,所以我使用sed去掉空白。

Remove the number from the directory, if one exists, so we can re-run this multiple times and not end up with names that look like this: 2-3-dir, and also check that the newdirname is not the same as CURDIR; if it is, there's no point running mv.

从目录中删除该号码(如果存在),这样我们就可以多次重新运行这个号码而不是最终使用如下所示的名称:2-3-dir,并检查newdirname与CURDIR是否相同;如果是的话,没有必要运行mv。


#!/bin/bash

TARGETPATH=.
for CURDIR in `ls -l $TARGETPATH`
do
  if [ -d $TARGETPATH/$CURDIR ]; then
    echo "$CURDIR is a directory"
    #Also strip whitespace from FILECOUNT
    FILECOUNT=$(ls -l $CURDIR | grep ^- | wc -l | sed -e 's/[ \t]*//')
    echo " and there are $FILECOUNT file(s)";

    # We should remove the number from the directory.
    newdirname="$FILECOUNT"-"$(echo "$CURDIR" | sed -e 's/^[0-9]*-//')"
    echo " New directory name: ["$newdirname"]"
    # Now we move the old-dir to the new-dir. 
    if [[ "$CURDIR" != "$newdirname" ]]; then
    mv $TARGETPATH/$CURDIR $TARGETPATH/$newdirname
    fi  
  fi  
done

#1


3  

before

.
├── d1
│   ├── f1
│   ├── f2
│   └── f3
├── d2
│   ├── f4
│   └── f5
└── d3
    ├── d4
    │   └── f9
    ├── f6
    ├── f7
    └── f8

run the command at top level dir

cd /home/pritchea/test

for i in *
do
    [[ -d $i ]] || continue
    n=${i#*-}
    c=$(find "$i" -type f -printf x | wc -c)
    [[ $i == $c-$n ]] && continue
    mv -f "$i" "$c-$n"
done

after

.
├── 2-d2
│   ├── f4
│   └── f5
├── 3-d1
│   ├── f1
│   ├── f2
│   └── f3
└── 4-d3
    ├── d4
    │   └── f9
    ├── f6
    ├── f7
    └── f8

#2


0  

This is the way I did it. I loop over all the directories in $TARGETPATH, using ls -l to check how many files that are not directories exist in each $CURDIR. Note: this might not be the best method (find -f might give better results; I haven't checked with symlinks etc).

这就是我做的方式。我遍历$ TARGETPATH中的所有目录,使用ls -l检查每个$ CURDIR中有多少个不是目录的文件。注意:这可能不是最好的方法(查找-f可能会给出更好的结果;我没有检查过符号链接等)。

Because wc -l tends to give output that looks similar to [ 1], rather than [1], I strip the whitespace using sed.

因为wc -l倾向于给出类似于[1]而不是[1]的输出,所以我使用sed去掉空白。

Remove the number from the directory, if one exists, so we can re-run this multiple times and not end up with names that look like this: 2-3-dir, and also check that the newdirname is not the same as CURDIR; if it is, there's no point running mv.

从目录中删除该号码(如果存在),这样我们就可以多次重新运行这个号码而不是最终使用如下所示的名称:2-3-dir,并检查newdirname与CURDIR是否相同;如果是的话,没有必要运行mv。


#!/bin/bash

TARGETPATH=.
for CURDIR in `ls -l $TARGETPATH`
do
  if [ -d $TARGETPATH/$CURDIR ]; then
    echo "$CURDIR is a directory"
    #Also strip whitespace from FILECOUNT
    FILECOUNT=$(ls -l $CURDIR | grep ^- | wc -l | sed -e 's/[ \t]*//')
    echo " and there are $FILECOUNT file(s)";

    # We should remove the number from the directory.
    newdirname="$FILECOUNT"-"$(echo "$CURDIR" | sed -e 's/^[0-9]*-//')"
    echo " New directory name: ["$newdirname"]"
    # Now we move the old-dir to the new-dir. 
    if [[ "$CURDIR" != "$newdirname" ]]; then
    mv $TARGETPATH/$CURDIR $TARGETPATH/$newdirname
    fi  
  fi  
done