Ulangi file dengan spasi di namanya, buat folder baru dari karakter pertama di setiap file dan pindahkan file ke folder

1

Saya mencoba untuk mengeksekusi skrip bash ini yang mengulang file (yang memiliki spasi dalam nama) di direktori saat ini dan membuat folder baru dengan karakter pertama file (jika belum dibuat) dan memindahkan file itu ke folder . Ini kode saya:

for i in `/bin/ls | xargs`
do
    dir=`echo "$i" | cut -c 1 -`
    mkdir -m777 -p "$dir"
mv "$i" "$dir"
done

Masalah dengan ini tampaknya karena ia memperlakukan setiap kata dalam file sebagai file terpisah, jadi meskipun ia membuat folder dengan benar, itu tidak dapat memindahkan file ke folder itu karena nama file yang dicari adalah hanya kata pertama dari file aktual. Saya melihat jawaban lain untuk pertanyaan serupa tetapi ini adalah yang terdekat yang bisa saya dapatkan.

EDIT: Saya mengganti "for i in /bin/ls | xargs " dengan "for i in *" seperti yang disarankan @steeldriver, dan meskipun itu memperbaiki masalah asli saya, saya mendapatkan kesalahan seperti ini:

mv: cannot move '`' to a subdirectory of itself, '`/`'
mv: invalid option -- ' '
mv: missing destination file operand after '-'
mv: invalid option -- '.'
mv: invalid option -- ')'
mv: invalid option -- '+'
mv: cannot move ''$'\340' to a subdirectory of itself, ''$'\340''/'$'\340'
mv: cannot move ''$'\303' to a subdirectory of itself, ''$'\303''/'$'\303'
mv: cannot move ''$'\305' to a subdirectory of itself, ''$'\305''/'$'\305'
mv: invalid option -- '1'

Saya pikir beberapa file ini mungkin dimulai dengan karakter non-ascii (saya tidak dapat melihat konten karena ada terlalu banyak file). Apakah ada cara untuk menangani kasus ini?

Logan
sumber
1
for i in *; do ...- lihat Bash Pitfall # 1
steeldriver
Selamat datang di Unix & Linux! Biasanya ide yang sangat buruk untuk mengurai output ls. Anda mungkin harus melihat ke dalam menggunakan findatau shell globbing sederhana untuk mendapatkan daftar file Anda untuk diproses. Bacaan lebih lanjut tentang subjek ini dapat ditemukan di sini .
DopeGhoti
Juga, ini akan gagal jika Anda sudah (misalnya) memiliki file yang dipanggil t.
DopeGhoti

Jawaban:

2

Untuk mengulang file dengan spasi di namanya, shellnya banyak, tidak perlu memanggil ls:

for    i in *                   # * replaces the complex (and unquoted) `/bin/ls | xargs`
do
       dir=${i%"${i#?}"}        # replaces the slow subshell `echo "$i" | cut -c 1 -`

       echo "$i"                # just to show that an * is enough (and accepts spaces).
done

Dan untuk memproses setiap file yang terdaftar (yang termasuk direktori) Anda harus memeriksa bahwa nama file adalah file (bukan direktori) dan juga memeriksa apakah direktori tersebut tidak ada sebelum membuatnya.

for i in *
do
    if [ -f "$i" ]; then
        dir=${i%"${i#?}"}
        if [ ! -d "$dir" ]; then
            mkdir -m777 -p "$dir"
        fi
        mv "$i" "$dir"
        if [ "$?" -ne 0 ]; then
            echo "An error occurred moving file \"$i\" to dir \"$dir\""
        fi
    fi
done
Ishak
sumber
0

Dengan GNU Parallel, tampilannya seperti ini:

parallel 'mkdir -p {=s/(.).*/$1/=}; mv {} {=s/(.).*/$1/=}' ::: *

(Sunting: Baru saja dicatat Anda meminta file - bukan dir. / Dihapus).

Ole Tange
sumber
Ketika saya mencoba ini, saya mendapatkan kesalahan: mv: tidak dapat memindahkan ' /' ke subdirektori itu sendiri, '* / '
Logan