🤔

Linuxで特定のディレクトリ内のファイル名をもとに新しいファイルを作成する

2020/12/05に公開4

MacOSで特定のディレクトリ内のファイル一覧を取得して、そのファイル名をもとにして新しいファイルを作成する必要があったのでその備忘録です。

例えばこんな感じでファイルがあったら、このディレクトリの中のファイルの拡張子を変えたものをコピーして作成します。

ディレクトリ
  - hoge.txt
  - fuga.txt

⬇⬇ 拡張子を書き換えたファイルを作成 ⬇⬇

別のディレクトリ
  - hoge.md
  - fuga.md

lsの出力結果をループ処理

lsで出力したファイル名一覧はこんな感じでループ処理できます。

for filename in `ls ./dirname`; do
  # 処理
done

置換して出力

lsの結果を置換して出力するためにはls ./dirname | sed -e s/置換対象の文字列/置換後の文字列/gという感じで書きます。

例として「.txt」から「.md」に書き換えるならls ./dirname | sed -e s/\.txt/\.md/gみたいな感じです。ひとつずつ書き換えしたうえで出力するなら下記みたいになると思います。

# `hoge.txt`と`fuga.txt`があるディレクトリを指して実行すると

for filename in `ls ./dirname | sed -e s/\.txt/\.md/g`; do
  echo $filename
done

# hoge.md
# fuga.md

新しいファイルを作成

これだとまだ置換されたファイル名が出力されただけなので新しいファイル名でファイルを作成してみます。空のファイルを作成するならtouchコマンドですね。

# `hoge.txt`と`fuga.txt`があるディレクトリを指して実行すると

for filename in `ls ./dirname | sed -e s/\.txt/\.md/g`; do
  touch "./new_dirname/$filename"
done

# new_dirnameディレクトリ内に hoge.md と fuga.md が作られる

Linuxでも同じコマンドが使えるはずです。うーん、もっと簡単に書けるような気がします

Discussion

WATANABE KoheiWATANABE Kohei

Bashであればファイル名展開とパラメーター展開を使うと比較的シュッとかけるかなと思います。

https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html#Pattern-Matching
https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html#Shell-Parameter-Expansion

Zshなどについてもおそらく同様の機能はあるかなと思います。
ご参考までに。

例:

for filename in dirname/*.txt; do
  touch "./new_dirname/${filename%.txt}.md"
done
にゃーんにゃーん

なんと、こんなに簡潔に書けるのですね❗ありがとうございます❗

坦々狸坦々狸

私ならループ使うと混乱するからtxtあるディレクトリで

$ cp *.txt new_dirname/ # txtファイルをnew_dirnameへコピー
$ truncate --size 0 ./new_dirname/*.txt # コピーしたファイルを空にする
$ rename.ul .txt .md new_dirname/* # new_dirnameにあるファイルの拡張子をリネーム

こうかな

touchコマンド使ってたので空ファイルにしてますがコピーしたファイルそのままでいいなら
truncateコマンドは不要です

td-shitd-shi

曲芸としてはかなり微妙だけど, 供養代わりに. sedxargs -I% sh -c '%'によるループなしのワンライナー.

/tmp/org$ ls
fuga.txt  hoge.txt
/tmp/org$ find . -type f -name \*.txt | sed "s:^\(.*\)/\([^/]*\)\.txt$:cp \1/\2.txt ../tag/\2.md:g" | xargs -I% sh -c '%'
/tmp/org$ ls ../tag
fuga.md  hoge.md

つまり, sed で実行するコマンドを組み立てて, xargsでそれを実行している.
sedのパートで同様に1行で書けるなら任意の処理ができるんじゃないかな.