【Shell】シェル ~ ファイル処理あれこれ ~

■ はじめに

シェルで何かを行う際に、あの時のあの処理ってどう書いたっけ?
ってことが多いので、メモ。

目次

【1】ファイル名を取り出す
【2】ファイル内容を表示する
【3】特定の拡張子でループさせる
【4】拡張子を別拡張子に置き換える
【5】ファイル・ディレクトリのチェック(存在チェックなど)

【1】ファイル名を取り出す

# ファイル名を取り出す => hello.txt
basename '/a1/b2/hello.txt'

https://qiita.com/ktr_type23/items/94747a4b27e8a630ce48

補足:URLでも可能

$ basename https://github.com/your-account/your-repo-1.git
your-repo-1.git

【2】ファイル内容を表示する

cat test.txt | grep -v '^$' | while read line;
do
  echo $line 
done

# 空白行も表示
while IFS= read -r line; do    
    echo "$line"
done < bk_docker-compose-local.yml

サンプル

どうせなら、以下の関連記事でやった関数化で書いてみる

https://dk521123.hatenablog.com/entry/2015/03/17/233124
例1

cat() {
  file_path=${1}
  while read line
  do
    echo $line
  done < file_path
}

cat ./hello_world.txt

例2 : ファイル一覧を表示(TEXTファイルのみ)

#! /bin/bash

readonly DIRS=("$@")

for dir in ${DIRS[@]}; do
  echo "*[${dir}]****************"
  for file in `ls ${dir}/*.txt | sort -n`
  do
    echo "File = ${file}"
  done
  echo "*************************"
done

参考文献
https://www.server-memo.net/shellscript/read-file.html

【3】特定の拡張子でループさせる

例1:拡張子「txt」でループさせた場合

for target_file in `ls /home/admin/path1/*.txt`
do
  # ここにループ処理を書く
  echo target_file 
done

応用:二重ループ

#!/bin/bash

readonly ROOT_PATH=${1}

for root_dir in `ls ${ROOT_PATH}`
do
  if [ -f ${root_dir} ]; then
    echo "=== Skip : ${root_dir} ==="
    continue
  fi
  
  if [ ${root_dir} = "test" ]; then
    echo "==== Skip : ${root_dir} ===="
    continue
  fi
  
  echo "*** Starting to loop - ${root_dir} ***"
  for sub_path in `ls ${root_dir}`
  do
    # ここにループ処理を書く
    echo ${sub_path}
  done
done

【4】拡張子を別拡張子に置き換える

例1:拡張子「temp」を「txt」に置き換えたファイル名を取得する

for target_file in `ls /home/admin/path2/*.temp`
do
  replaced_file_extension="txt"
  other_file=`echo ${target_file} | sed -r "s/(.*).txt$/\1.${replaced_file_extension}/"`
  echo target_file 
done

【5】ファイルのチェック(存在チェックなど)

https://takuya-1st.hatenablog.jp/entry/2014/01/24/150236

 * -e file : ファイルが存在する場合、true
 * -f file : ファイルの場合、true
 * -s file : ファイルが存在し、サイズが 0 より大きい場合、true
 * -w file : ファイルが存在し、書き込み可能である場合、true
 * -r file : ファイルが存在し、読み取り可能である場合、true
 * -d file : ディレクトリの場合、true

例1

if [ -e $file ]; then
    echo "$file found."
else
    echo "$file NOT found."
fi

例2

if [! -e ${file}]; then
   echo "Not Found!"
fi

 応用

 * 指定のディレクトリ内にファイルが存在するかを調べる場合

例1

if [ -z "`ls ${target_dir}`" ]; then
    # fileが存在しなかった場合
    echo "No file in ${target_dir}."
fi

例2

if [ ls *.txt > /dev/null 2>&1 ]; then
    # fileが存在しなかった場合
    echo "No file in ${target_dir}."
fi

補足 「ls > /dev/null 2>&1」について

 * /dev/nullへの出力は、ディスクに書き込まれることなくすべて破棄される
 (ゴミ箱のようなイメージ)
 * 「2 : エラー出力」「1 : 標準出力」で
  「"2>&1" は、エラー出力(2)を標準出力(1)にまとめる」
   (ちなみに、「0 : 標準入力」)

関連記事

シェル ~入門編~
https://dk521123.hatenablog.com/entry/2014/10/23/005406
シェルスクリプトあれこれ
https://dk521123.hatenablog.com/entry/2018/03/03/210642
JDBCシェルスクリプトでパースする ~ bashによる文字列置換 ~
https://dk521123.hatenablog.com/entry/2020/03/24/223323
テキスト加工 ~ sed / awk
https://dk521123.hatenablog.com/entry/2019/11/22/223043