什麼命令列可以可靠地遍歷多個目錄級別

什麼命令列可以可靠地遍歷多個目錄級別

我遇到了與所問問題相同的問題 重命名缺少檔案副檔名的音樂文件 我發現@Gilles 提供的腳本非常有教育意義,但不幸的是它沒有按我預期的方式運作。我正在尋找的是一個腳本,它可以為所有子目錄、所有層級、「/path/to/music/directory/」下面的所有音樂檔案新增檔案副檔名,而無需擴展名。建議的命令列參數

/path/to/music/directory/{**/,}*

讓腳本遍歷「/path/to/music/directory/」以下一級子目錄中的所有文件,但不遍歷該子目錄下的所有文件。我應該使用什麼命令列參數來遍歷「directory/」以下各級的所有檔案?

也將不勝感激指向文件的指針

{**/,}* 

部分。

順便說一句,對於那些對原始答案感興趣的人。我發現更改行後腳本效果更好

file -i "$@" |

file --mime-type "$@" | 

(如果我有特權級別,我會在原始答案中將此作為評論給出)

答案1

我認為你只需要啟動 bashglobstar選項,因為預設情況下它不是活動的烏班圖,如下所述。

這個表達式/path/to/music/directory/{**/,}*包含兩個擴展結構:一個大括號擴展和一個路徑名擴展。

支撐擴張

用一個例子最好解釋大括號擴展:

$ printf '%s\n' before-{a,bb,1,22}-after
before-a-after
before-bb-after
before-1-after
before-22-after

(我在這裡和下面使用了printf '%s\n' item1 item2 etc..類似於echo但在新行上列印每個元素的命令)

您會看到大括號中的每個逗號分隔的元素都會產生一個展開的元素。

原始範例包含在大括號中的元素**/和一個空元素,擴展為

$ printf '%s\n' /path/to/music/directory/{**/,}*
/path/to/music/directory/**/*
/path/to/music/directory/*

戒指球星

現在轉向 bash glob **,它在bash 手冊頁,都與 shell 選項 相關globstar,意思如下:

路徑名擴展上下文中使用的模式 ** 將匹配檔案以及零個或多個目錄和子目錄。

這個 shell 選項不是積極的Ubuntu 預設:

$ shopt globstar
globstar        off

您可以使用以下命令來啟動它

shopt -s globstar

(用於shopt -u globstar停用它)。

如果我們有以下目錄結構:

$ find first/ | sort
first/
first/aaa
first/second
first/second/bbb01
first/second/bbb02
first/second/third
first/second/third/ccc1
first/second/third/ccc2
first/second/third/ccc3

我們可以進行以下擴充:

$ printf '%s\n' first/**/a*
first/aaa

$ printf '%s\n' first/**/b*
first/second/bbb01
first/second/bbb02

$ printf '%s\n' first/**/c*
first/second/third/ccc1
first/second/third/ccc2
first/second/third/ccc3

所以你可以看到它**能夠擴展到不只是一個路徑名元素。

答案2

我會做這樣的事情

#! /bin/bash

[[ -d "$1" ]] || { echo "$1 not a directory, exiting..."; exit 1; }

find "$1" -type f | while read F; do
  # do what you want with the "$F"
done

exit 0

然後透過呼叫腳本./my_script <directory>

相關內容