ディレクトリ/home/username/data
には、ファイルとディレクトリの両方があります。これらのファイル名の一部は.txt
で終わります(これをテキストファイルと呼びます)。同じことがサブディレクトリでも起こります。
サブディレクトリの1つはother_files
と呼ばれます(その完全パスは/home/username/data/other_files/
です)。
.txt
で終わらないすべてのファイルを移動したいのルート/home/username/data
をother_files
に移動します。
ループでできるかもしれませんが、それは私が望んでいることではありません。コマンドとパイピングを使用したい。これは簡単だと私は信じています。 mv
、find
、grep
とxargs
の組み合わせで実現できますが、方法はわかりません。
だから私はテキストファイルを一致させようとするのに行き詰まっています(それからそれらを除くすべてのものを一致させる方法を考えるために)。以下では、現在のディレクトリが/home/username/data
であると想定しています。
最初に私はfind . | grep -E "*\.txt"
に行きましたが、これはサブディレクトリにあるものを含むすべてのテキストファイルに一致します。
そこで、私はfind . | grep -E "\./*\.txt"
を試して、同じマッチが得られるかどうかを確認し、目標に向かって進んでいきましたが、これは何にもマッチせず、ここが行き詰まっています。
質問の最初に説明したことをするにはどうすればよいですか?
単純なシェルループバリアント(bash
内):
_shopt -s extglob dotglob nullglob
for pathname in ~username/data/!(*.txt); do
! test -d "$pathname" && mv "$pathname" ~username/data/other_files
done
_
最初の行で設定されたシェルオプションは、bash
シェルが拡張グロビングパターン(!(*.txt)
で_.txt
_で終わらないすべての名前に一致する)を有効にし、グロブパターンが一致するようにします隠された名前で、何も一致しない場合、パターンは何にも拡張されません。
ループの本体は、ディレクトリ(またはディレクトリへのシンボリックリンク)であるものはすべてスキップし、それ以外のすべてを指定されたディレクトリに移動します。
find
およびGNU mv
と同等のもの(存在する場合はシンボリックリンクをディレクトリに移動し、mv
を一度にできるだけ多くのファイルを使用できますが、それらだけが違います)。
_find ~username/data -maxdepth 1 ! -type d ! -name '*.txt' \
-exec mv -t ~username/data/other_files {} +
_
関連:
find /home/username/data -maxdepth 1 -type f ! -name '*.txt' -exec mv {} /home/username/data/other_files/ \;
このコードは、「。txt」で終わっていないすべてのファイルをターゲットフォルダーに移動しますが、異なるパスに同じ名前のファイルがある場合、エラーがスローされます。
find /home/username/data ! -name "*.txt" -type f -maxdepth 1 -exec mv {} /home/username/data/other_files/ \;
次の行は、現在のディレクトリで*.txt
ではなく、パスでもないすべてのファイルと隠しファイルを見つけ、それらをnewpathに移動します。
ls -1p | grep -v "^.*\.txt$" | grep -v ".*/$" | xargs mv -vt newpath
以下は同じですが、隠しファイルも移動します:
ls -1ap | grep -v "^.*\.txt$" | grep -v ".*/$" | xargs mv -vt newpath
両方のコマンドラインはディレクトリを再帰的にスキャンせず、ディレクトリを移動しません
スペースを含むファイル名がある場合は、次を使用できます。
ls -1ap | grep -v "^.*\.txt$" | grep -v ".*/$" | xargs -d'\n' printf "\"%s\"\n" | xargs mv -vt newpath