ファイルがディレクトリの場合は移動しないでくださいmv bash

ファイルがディレクトリの場合は移動しないでくださいmv bash

私はファイルを整理するのに役立つスクリプトを書いています。デフォルトでは、スクリプトは拡張子に従ってファイルを構成したいと思います。現在のソリューションは、特定のディレクトリのすべてを調べます。名前にドットがあるフォルダが移動されるため問題になります。

if statementディレクトリが物理ディレクトリであることを確認するために使用できる方法があるかどうか疑問に思います。実際にディレクトリの場合、スクリプトはディレクトリを移動しないでください。

コード部分です。私はfor loopファイルを繰り返すためにaを使用しています。これはWindowsにあった以前のバッチスクリプトに大まかに基づいているため、これが最善のアプローチではない可能性があります。より良い解決策があれば教えてください。

#!/bin/bash
for i in *.*; do
  filename=$(basename -- "$i")
  extension="${filename##*.}"
  extension="$extension"files
  mkdir -p "$extension"
  mv "$i" "$extension"
done

答え1

個人的には、forディレクトリ/ファイルを使用してそれぞれファイル形式を指定できるfindため、aとループを使用します。while-type d/f

実行するディレクトリの「行」として:

find . -maxdepth 1 -type f -name "*.*" | while IFS="" read -r line; do filename=$(basename -- "$line"); extension="${filename##.}.files"; mkdir -p "$extension"; mv "$line" "$extension"; done

またはスクリプトから:

#!/bin/bash
find . -maxdepth 1 -type f -name "*.*" |
while IFS="" read -r line; do
    filename=$(basename -- "$line")
    extension="${filename##.}.files"
    mkdir -p "$extension"
    mv "$line" "$extension"
done

説明する

find .- 現在のディレクトリでファイルとディレクトリを探す

-maxdepth 1- 現在のディレクトリのみを確認します。 (2は次のレベルディレクトリも確認します。)

-type f- ファイルのみ一致

-name *.*- 名前に「.」を含むすべてのファイル

.files私もそれがあなたが望むものだと思うので、拡張を変数宣言に変更しました。現在スクリプトにあるようにtmp.txtディレクトリにあると言いたい場合は、次のように「.」を削除します。tmp.txtfiles

extension="${filename##.}files"

編集する:

したがって、@Kusalanandaが指摘したように、aを繰り返すのはfindおそらく悪い考えです。それにもかかわらず、findこの機能を引き続き使用できます。一時ファイルを使用して繰り返します。

#!/bin/bash
find . -maxdepth 1 -type f -name "*.*" > myTemporaryFile

IFS=$'\n' # in case any filenames have spaces in them

for line in $(cat myTemporaryFile); do
    filename=$(basename -- "$line")
    extension="${filename##.}.files"
    mkdir -p "$extension"
    mv "$line" "$extension"
done

rm myTemporaryFile

答え2

私は Kusalananda のコメントから 1 つ、もう 1 つは完全に異なる 2 つの方法を提案します。

まず、bash(および他のシェル)にはディレクトリであることをtest確認する単純な演算子があります。[ -d something ]次のように使用できます。

#!/bin/bash
for i in *.*; do
  [ -d "$i" ] && continue
  # ... rest of the script
done

上記のコードは、*.*ワイルドカードの各「ファイル」を調べて、ディレクトリであることを確認します。ディレクトリの場合、テストに合格し、ループが次の項目(存在する場合)に進みます。

あるいは、幅広いワイルドカード機能を備えたzshを使用できます。そのうちの1つは、特定の種類のファイル(通常のファイル、ディレクトリなど)の一致を制限することです。次のように使用できます。

#!/bin/zsh
for i in *.*(.)
do
  # ... rest of your script
done

の特別な構文は(.)次のとおりです。「グローバル予選」;括弧は修飾子であることを示し、ピリオドは通常のファイルを探していることを示します。その結果、forループはディレクトリではなくファイルのみに一致します。

答え3

以下を使用してファイルであることを確認できます-fif

if [ -f "${i}" ];then
  echo "${i} is a file."
else
  echo "${i} is not a file."
fi

-dディレクトリであることを確認するために使用でき、!ロジックを反転するためにプレフィックスを追加できます。つまり、変数がファイルではないことを確認します。

if [ ! -f "${i}" ];then
  echo "${i} is not a file"
fi

関連情報