🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Q&A

解決済

3回答

5119閲覧

スペースを含んだファイルも含めてforしたい

退会済みユーザー

退会済みユーザー

総合スコア0

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

0グッド

0クリップ

投稿2020/11/26 07:21

編集2020/11/27 01:57

指定のディレクトリ(サブディレクトリ含む)から条件に一致するファイル名を出して処理をしていくスクリプトを作りたい。
findとforを組み合わせて作りましたが、空白スペースが入っているようなファイル(例:aaa aaa.txt)が存在するとうまく処理ができない問題があります。

for file in `find ディレクトリ名 -type f -name '*.txt' 2>/dev/null`; do

調べて見るとやりたいことを実現できそうな記事がありましたが、ここに書いてあるコードを試してみるとエラーになります。

syntax error near unexpected token `<'

コピペミスではないと思いますが、使え無さそうなので他に実現する方法はありませんでしょうか?


追記:参考にしたページのものは動作するという回答を頂いておりますが、やはりこちらの環境では動作しないように思えます。
DockerのCentOSを使っておりそれが問題なのかどうかがわかりませんが、テスト用に作成したスクリプトと環境を記述しておきます。

環境

[root@bbec28a1ab2f ~]# uname -a Linux bbec28a1ab2f 5.4.39-linuxkit #1 SMP Fri May 8 23:03:06 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux [root@bbec28a1ab2f ~]# bash --version GNU bash, version 4.4.19(1)-release (x86_64-redhat-linux-gnu) Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. [root@bbec28a1ab2f ~]# find --version find (GNU findutils) 4.6.0 Copyright (C) 2015 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Eric B. Decker, James Youngman, and Kevin Dalley. Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS(FTS_CWDFD) CBO(level=2)

動作テスト用スクリプト

#!/bin/bash while read f; do echo "${file}" done < <(find . -type f)

実行結果

# sh test.sh test.sh: line 5: syntax error near unexpected token `<' test.sh: line 5: `done < <(find . -type f)'

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2020/11/26 07:36

具体的にひっかかりそうなファイル名を例示してもらえますか?
Daregada

2020/11/26 08:12

> ここに書いてあるコードを試してみるとエラーになります。 こちらの環境ではリンク先のページのコードはエラーにならないので、「ここに書いてあるコードを試してみる」ときに使ったコードを提示してください。
guest

回答3

0

参照されたページの内容は概ね正しいです。

syntax error near unexpected token `<'

おそらく、BashやZshでないシェルで実行したのでしょう。
シェルスクリプトをbashかzshで実行してください。

ちゃんとチェックしてませんが、空白がファイル名の先頭や末尾にあると駄目な気がします。

投稿2020/11/26 08:12

otn

総合スコア85893

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2020/11/26 10:34

ループの中で何をやりたいかにもよります。 シェル変数に何かセットして、ループ終了後にその変数を参照したいと言うことでなければ、 find ~~~ | xags -i ~~~ {} が簡単です。
otn

2020/11/27 03:40

> # sh test.sh > test.sh: line 5: syntax error near unexpected token `<' だから、sh じゃなくて bash を使えと書いたのですが。 bash test.sh です。
otn

2020/11/27 03:44

> ちゃんとチェックしてませんが、空白がファイル名の先頭や末尾にあると駄目な気がします。 末尾の空白が落ちますね。末尾にも空白があり得る場合は、whileの前で IFS= してください。(IFSに空をセットする)
guest

0

ベストアンサー

空白を含むファイル名でも動くのは「TL;DR」に書いてあるやつですよ。findが-print0オプションによってヌル文字を出力の区切りとして使い、bashのreadコマンドも-dオプションでヌル文字を入力の区切りとして使うようになってます。

あなたの書いたスクリプトに合わせると、こんな感じになるはず。

bash

1#!/bin/bash 2 3while read -d $'\0' file; do 4 echo "${file}" 5done < <(find . -type f -print0)

補足: あなたがスクリプトの実行自体に失敗しているのは、「bash」ではなく「sh」コマンドでスクリプトを読み込んでいるからです。CentOSにおける「sh」の実体はbashですが、shコマンドでスクリプトを実行するとsh互換のbash posixモードで動作します。すると、オリジナルのshにはない機能(プロセス置換など)がオミットされるので、提示されたエラーが発生します。

投稿2020/11/27 02:11

編集2020/11/27 02:16
Daregada

総合スコア11990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ubuntuで試したところでは、スペースをファイル名に含むファイルでも以下で普通にうまく出来ているように見えます。

find ディレクトリ名 -type f -name '*.txt' | xargs -i 実行したいコマンド {}

シェルやfindのバージョンによってはダメかもしれません。私の環境はこんな感じ。

$ uname -a Linux biolinux 4.4.0-148-generic #174~14.04.1-Ubuntu SMP Thu May 9 08:17:37 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux $ bash --version bash --version GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu) $ find --version find (GNU findutils) 4.4.2

https://unix.stackexchange.com/questions/81349/how-do-i-use-find-when-the-filename-contains-spacesには、find -print0xargs -0を使う方法が紹介されていました。

find ディレクトリ名 -type f -name '*.txt' -print0 | xargs -0 -i 実行したいコマンド '{}'

投稿2020/11/26 08:28

KojiDoi

総合スコア13692

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問