基于文件名的一部分创建文件夹

huangapple go评论59阅读模式
英文:

Creating folders based on part of a filename

问题

我在 macOS 上的一个文件夹中有一堆有声书。文件命名结构是 `作者 - 标题.m4b`(例如 `JRR Tolkien - 魔戒.m4b`)。我想运行一个 bash 脚本,然后得到以下文件夹结构:

 - 作者(文件夹)
   
 - --> 标题(文件夹)
   
 - ----> 保持不变的有声书 m4b 文件(如上命名)

因此文件将位于作者文件夹中的书籍文件夹中。

我找到了这个脚本:

```bash
find . -type f -name "*jpg" -maxdepth 1 -exec bash -c 'mkdir -p "${0%%_*}"' {} \; \
-exec bash -c 'mv "$0" "${0%%_*}"' {} \;

但它“仅”将作者作为文件夹并将文件放在其中。我还没有找到一种方法来获取标题并将其作为另一子文件夹级别。


<details>
<summary>英文:</summary>

I have a bunch of audiobooks in one folder on macOS. The file naming structure is `Author - Title.m4b` (e.g. `JRR Tolkien - Lord of the Rings.m4b`). I would like to run a bash script and then have the following folder structure:

 - Author (folder)
   
 - --&gt; Title (folder)
   
 - ----&gt; Audiobook m4b file (naming as above, unchanged)

So the file would be in the book folder in the author folder.

I have found this script:

    find . -type f -name &quot;*jpg&quot; -maxdepth 1 -exec bash -c &#39;mkdir -p &quot;${0%%_*}&quot;&#39; {} \; \
    -exec bash -c &#39;mv &quot;$0&quot; &quot;${0%%_*}&quot;&#39; {} \;


But it &quot;only&quot; takes the author as a folder and puts the file in there. I have not found a way to take the title and make this another subfolder level.

</details>


# 答案1
**得分**: 2

使用给定的文件名结构,结合 `sh`、`mkdir` 和 `mv`,类似以下方式:

```lang bash
#!/bin/sh

for file in ./*.m4b; do
  author=&quot;${file%% *}&quot;
  file_name=&quot;${file##* }&quot;
  title=&quot;${file_name%.*}&quot;
  echo mkdir -p &quot;$author/$title&quot; &amp;&amp;
  echo mv -v &quot;$file&quot; &quot;$author/$title/$file_name&quot;
done

输出:

mkdir -p ./Author/Title
mv -v ./Author - Title.m4b ./Author/Title/Title.m4b

去掉所有的 echo 后,在我的一侧输出如下:

renamed &#39;./Author - Title.m4b&#39; -&gt; &#39;./Author/Title/Title.m4b&#39;

这应该处理带有空格的文件名。

#!/bin/sh

for file in ./*.m4b; do
  author=${file%% -*}
  file_name=${file##*- }
  title=${file_name%.*}
  echo mkdir -p &quot;$author/$title&quot; &amp;&amp;
  echo mv -v &quot;$file&quot; &quot;$author/$title/$file_name&quot;
done

使用 bashv4+=~ 运算符。

#!/bin/bash

regexp=&#39;^(.+) - (.*)\.(.+)$&#39;
for file in ./*.m4b; do
  [[ $file =~ $regexp ]] &amp;&amp;
  author=${BASH_REMATCH[1]}
  title=${BASH_REMATCH[2]}
  file_name=${BASH_REMATCH[2]}.${BASH_REMATCH[3]}
  echo mkdir -p &quot;$author/$title&quot; &amp;&amp;
  echo mv -v &quot;$file&quot; &quot;$author/$title/$file_name&quot;
done

输出:

mkdir -p ./Author/Title
mv -v ./Author - Title.m4b ./Author/Title/Title.m4b
mkdir -p ./Dan Brown/Diabolus
mv -v ./Dan Brown - Diabolus.m4b ./Dan Brown/Diabolus/Diabolus.m4b
mkdir -p ./JRR Tolkien/Lord of the Rings
mv -v ./JRR Tolkien - Lord of the Rings.m4b ./JRR Tolkien/Lord of the Rings/Lord of the Rings.m4b

去掉 echo 后:

renamed &#39;./Author - Title.m4b&#39; -&gt; &#39;./Author/Title/Title.m4b&#39;
renamed &#39;./Dan Brown - Diabolus.m4b&#39; -&gt; &#39;./Dan Brown/Diabolus/Diabolus.m4b&#39;
renamed &#39;./JRR Tolkien - Lord of the Rings.m4b&#39; -&gt; &#39;./JRR Tolkien/Lord of the Rings/Lord of the Rings.m4b&#39;

tree 实用工具的输出:

Author/
└── Title
    └── Title.m4b
Dan Brown/
└── Diabolus
    └── Diabolus.m4b
JRR Tolkien/
└── Lord of the Rings
    └── Lord of the Rings.m4b

3 directories, 3 files
  • 如果你在与文件相同的目录中(相对路径)运行上述脚本,那么脚本将正常工作,否则请将 ./*.m4b 更改为绝对路径。
  • 参考 POSIX sh 参数扩展
  • 参考 Bash Shell 参数扩展
英文:

With your given file name structure, with sh, mkdir and mv something like this:

#!/bin/sh

for file in ./*.m4b; do
  author=&quot;${file%% *}&quot;
  file_name=&quot;${file##* }&quot;
  title=&quot;${file_name%.*}&quot;
  echo mkdir -p &quot;$author/$title&quot; &amp;&amp;
  echo mv -v &quot;$file&quot; &quot;$author/$title/$file_name&quot;
done

Output:

mkdir -p ./Author/Title
mv -v ./Author - Title.m4b ./Author/Title/Title.m4b

Without all the echo , the output is like this on my side:

renamed &#39;./Author - Title.m4b&#39; -&gt; &#39;./Author/Title/Title.m4b&#39;

This should handle your file names with spaces.

#!/bin/sh

for file in ./*.m4b; do
  author=${file%% -*}
  file_name=${file##*- }
  title=${file_name%.*}
  echo mkdir -p &quot;$author/$title&quot; &amp;&amp;
  echo mv -v &quot;$file&quot; &quot;$author/$title/$file_name&quot;
done

with bashv4+ with the =~ operator.

#!/bin/bash

regexp=&#39;^(.+) - (.*)\.(.+)$&#39;
for file in ./*.m4b; do
  [[ $file =~ $regexp ]] &amp;&amp;
  author=${BASH_REMATCH[1]}
  title=${BASH_REMATCH[2]}
  file_name=${BASH_REMATCH[2]}.${BASH_REMATCH[3]}
  echo mkdir -p &quot;$author/$title&quot; &amp;&amp;
  echo mv -v &quot;$file&quot; &quot;$author/$title/$file_name&quot;
done

Output:

mkdir -p ./Author/Title
mv -v ./Author - Title.m4b ./Author/Title/Title.m4b
mkdir -p ./Dan Brown/Diabolus
mv -v ./Dan Brown - Diabolus.m4b ./Dan Brown/Diabolus/Diabolus.m4b
mkdir -p ./JRR Tolkien/Lord of the Rings
mv -v ./JRR Tolkien - Lord of the Rings.m4b ./JRR Tolkien/Lord of the Rings/Lord of the Rings.m4b

Without the echo

renamed &#39;./Author - Title.m4b&#39; -&gt; &#39;./Author/Title/Title.m4b&#39;
renamed &#39;./Dan Brown - Diabolus.m4b&#39; -&gt; &#39;./Dan Brown/Diabolus/Diabolus.m4b&#39;
renamed &#39;./JRR Tolkien - Lord of the Rings.m4b&#39; -&gt; &#39;./JRR Tolkien/Lord of the Rings/Lord of the Rings.m4b&#39;
  • Remove all the echo if you're satisfied with the output.

Output from the tree utility:

Author/
└── Title
    └── Title.m4b
Dan Brown/
└── Diabolus
    └── Diabolus.m4b
JRR Tolkien/
└── Lord of the Rings
    └── Lord of the Rings.m4b

3 directories, 3 files

huangapple
  • 本文由 发表于 2023年5月29日 06:44:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76353862.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定