web-dev-qa-db-ja.com

特定の拡張子のないすべてのファイルにサフィックスを追加し、ファイル拡張子を保持する

.Zipファイルとその他のファイル(すべてのファイルhave拡張子)があるディレクトリがあり、すべてのファイルにサフィックスを追加したいwithout.Zip拡張子。サフィックスを取得して変数$suffixに配置できるため、次のコードを試しました。

ls -I "*.Zip"| xargs -I {} mv {} {}_"$suffix"

これは、.Zipのないすべてのファイルをリストし、閉じています(ただし間違っています)。 file.csvで次の結果が誤って生成されます。

file.csv_suffix

file_suffix.csvが必要です-コードを編集してファイルの拡張子を保持するにはどうすればよいですか?

5
kstats9pt3

find + bashアプローチ:

export suffix="test"

a)で検索-execアクション:

find your_folder -type f ! -name "*.Zip" -exec bash -c 'f=$1; if [[ "$f" =~ .*\.[^.]*$ ]]; then ext=".${f##*\.}"; else ext=""; fi; mv "$f" "${f%.*}_$suffix$ext"' x {} \;


b)またはbash whileループ:

find your_folder/ -type f ! -name "*.Zip" -print0 | while read -d $'\0' f; do 
    if [[ "$f" =~ .*\.[^.]*$ ]]; then
        ext=".${f##*\.}"
    else 
        ext=""
    fi
    mv "$f" "${f%.*}_$suffix$ext"
done
3
RomanPerekhrest

lsの使用は少し危険です。参照 `ls`を解析しない*理由*

また、ファイル名を分離する必要があります。そうでない場合は、発見したように、ファイル名の最後に_$suffix_を追加するだけです。

以下に、findを使用したソリューションと、findを使用しないソリューションを示します。


_find . -type f ! -name '*.Zip' -exec sh -c 'suffix="$1"; shift; for n; do p=${n%.*}; s=${n##*.}; [ ! -e "${p}_$suffix.$s" ] && mv "$n" "${p}_$suffix.$s"; done' sh "$suffix" {} +
_

これにより、名前が_.Zip_で終わらない、現在のディレクトリ内またはその下のすべての通常のファイルが検索されます。

次に、これらのファイルのリストを使用して次のシェルスクリプトが呼び出されます。

_suffix="$1"  # the suffix is passed as the first command line argument
shift        # shift it off $@
for n; do    # loop over the remaining names in $@
    p=${n%.*}    # get the prefix of the file path up to the last dot
    s=${n##*.}   # get the extension of the file after the last dot

    # rename the file if there's not already a file with that same name
    [ ! -e "${p}_$suffix.$s" ] && mv "$n" "${p}_$suffix.$s"
done
_

テスト:

_$ touch file{1,2,3}.txt file{a,b,c}.Zip
$ ls
file1.txt file2.txt file3.txt filea.Zip fileb.Zip filec.Zip

$ suffix="notZip"
$ find . -type f ! -name '*.Zip' -exec sh -c 'suffix="$1"; shift; for n; do p=${n%.*}; s=${n##*.}; [ ! -e "${p}_$suffix.$s" ] && mv "$n" "${p}_$suffix.$s"; done' sh "$suffix" {} +

$ ls
file1_notZip.txt    file3_notZip.txt    fileb.Zip
file2_notZip.txt    filea.Zip           filec.Zip
_

上記のシェルスクリプトは、ファイルの数がそれほど多くなく、サブディレクトリに再帰する必要がない場合(ファイル名以外をスキップするようにわずかに変更されている場合)は、findとは無関係に実行できます。

_#!/bin/sh

suffix="$1"  # the suffix is passed as the first command line argument
shift        # shift it off $@
for n; do    # loop over the remaining names in $@

    [ ! -f "$n" ] && continue  # skip names of things that are not regular files

    p=${n%.*}    # get the prefix of the file path up to the last dot
    s=${n##*.}   # get the extension of the file after the last dot

    # rename the file if there's not already a file with that same name
    [ ! -e "${p}_$suffix.$s" ] && mv "$n" "${p}_$suffix.$s"
done
_

bashを使用すると、次のようなディレクトリのファイルでこれを実行できます。

_$ shopt -s extglob
$ ./script.sh "notZip" !(*.Zip)
_

extglobシェルオプションをbashに設定すると、!(*.Zip)は、現在のディレクトリで_.Zip_で終わらないすべての名前に一致します。

4
Kusalananda

バッシュで:

shopt -s extglob
suffix=yoursuffix
for entry in !(*.Zip)
do
  [[ -f "$entry" ]] || continue
  base=${entry%.*}
  if [[ "$entry" =~ \. ]]
  then
    ext=${entry##*.}
    echo mv -- "$entry" "${base}_${suffix}.${ext}"
  else
    echo mv -- "$entry" "${base}_${suffix}"
  fi
done

echoが正しいと思われる場合は削除してください。

テストケース:

touch a.Zip b.Zip foo bar file.csv a.file.csv 'test case' 'test case.csv'
mkdir baz

出力例:

mv -- a.file.csv a.file_yoursuffix.csv
mv -- bar bar_yoursuffix
mv -- file.csv file_yoursuffix.csv
mv -- foo foo_yoursuffix
mv -- scr scr_yoursuffix
mv -- test case test case_yoursuffix
mv -- test case.csv test case_yoursuffix.csv

...ディレクトリbazをスキップしますが、fooとbarの名前を適切に変更します。

3
Jeff Schaller
 find <pathtodirectory> ! -name *.Zip | awk -v suff=$suffix -F\. '{ print $1"_"suff"."$2 }'

Findを使用してファイルを一覧表示し、awkを介して出力を解析できます。新しいサフィックスが含まれているファイルのリストに満足したら、awkのシステム関数を使用してawkからコマンドを再度実行し、作成してコマンドを実行します。

find <pathtodirectory> ! -name *.Zip | awk -v suff=$suffix -F\. '{ system("mv "$0" "$1"_"suff"."$2) }'

ただし、ソリューションにはコマンドインジェクションのリスクがあることに注意してください。また、ソリューションは、filename.extensionという構造を持つすべてのファイルに依存していることに注意してください。

1
Raman Sailopal