Saya memiliki skrip yang mencari semua file dalam beberapa subfolder dan arsip untuk tar. Skrip saya adalah
for FILE in `find . -type f -name '*.*'`
do
if [[ ! -f archive.tar ]]; then
tar -cpf archive.tar $FILE
else
tar -upf archive.tar $FILE
fi
done
Perintah find memberi saya output berikut
find . -type f -iname '*.*'
./F1/F1-2013-03-19 160413.csv
./F1/F1-2013-03-19 164411.csv
./F1-FAILED/F2/F1-2013-03-19 154412.csv
./F1-FAILED/F3/F1-2011-10-02 212910.csv
./F1-ARCHIVE/F1-2012-06-30 004408.csv
./F1-ARCHIVE/F1-2012-05-08 190408.csv
Tetapi variabel FILE hanya menyimpan bagian pertama dari path ./F1/F1-2013-03-19 dan kemudian bagian selanjutnya 160413.csv .
Saya mencoba menggunakan read
dengan loop sementara,
while read `find . -type f -iname '*.*'`; do ls $REPLY; done
tapi saya mendapatkan kesalahan berikut
bash: read: `./F1/F1-2013-03-19': not a valid identifier
Adakah yang bisa menyarankan cara alternatif?
Memperbarui
Seperti yang disarankan dalam jawaban di bawah ini saya memperbarui skrip
#!/bin/bash
INPUT_DIR=/usr/local/F1
cd $INPUT_DIR
for FILE in "$(find . -type f -iname '*.*')"
do
archive=archive.tar
if [ -f $archive ]; then
tar uvf $archive "$FILE"
else
tar -cvf $archive "$FILE"
fi
done
Output yang saya dapatkan adalah
./test.sh
tar: ./F1/F1-2013-03-19 160413.csv\n./F1/F1-2013-03-19 164411.csv\n./F1/F1-2013-03-19 153413.csv\n./F1/F1-2013-03-19 154412.csv\n./F1/F1-2012-09-10 113409.csv\n./F1/F1-2013-03-19 152411.csv\n./.tar\n./F1-FAILED/F3/F1-2013-03-19 154412.csv\n./F1-FAILED/F3/F1-2013-03-19 170411.csv\n./F1-FAILED/F3/F1-2012-09-10 113409.csv\n./F1-FAILED/F2/F1-2011-10-03 113911.csv\n./F1-FAILED/F2/F1-2011-10-02 165908.csv\n./F1-FAILED/F2/F1-2011-10-02 212910.csv\n./F1-ARCHIVE/F1-2012-06-30 004408.csv\n./F1-ARCHIVE/F1-2011-08-17 133905.csv\n./F1-ARCHIVE/F1-2012-10-21 154410.csv\n./F1-ARCHIVE/F1-2012-05-08 190408.csv: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors
IFS=$'\n'
sebelum `for loop untuk membuatnya parse di setiap barisJawaban:
Menggunakan
for
denganfind
adalah pendekatan yang salah di sini, lihat misalnya artikel ini tentang kaleng cacing yang Anda buka.Pendekatan yang disarankan adalah menggunakan
find
,while
danread
seperti yang dijelaskan di sini . Di bawah ini adalah contoh yang cocok untuk Anda:Dengan cara ini Anda membatasi nama file dengan
\0
karakter null ( ), ini berarti bahwa variasi dalam ruang dan karakter khusus lainnya tidak akan menimbulkan masalah.Untuk memperbarui arsip dengan file yang ditemukan
find
, Anda dapat meneruskan hasilnya langsung ketar
:Perhatikan bahwa Anda tidak harus membedakan antara apakah arsip itu ada atau tidak,
tar
akan menanganinya dengan bijaksana. Perhatikan juga penggunaan di-printf
sini untuk menghindari memasukkan./
bit dalam arsip.sumber
./
sebagai tar../.tar tar: ./archive.tar: file is the archive; not dumped
if [[ "$FILE" == "./" ]]; then
continue
./
bit dengan-printf
melihat jawaban yang diperbarui. Namun itu tidak akan membuat perbedaan jika dimasukkan atau tidak karena hanya referensi direktori saat ini. Saya juga menyertakanfind/tar
kombinasi alternatif yang mungkin ingin Anda gunakan.sort
hasil sebelum mengulanginya, Anda akan membutuhkansort -z
pemisah nol.Coba kutip
for
lingkaran seperti ini:Tanpa tanda kutip, bash tidak menangani spasi dan baris baru (
\n
) dengan baik ...Coba juga pengaturan
sumber
comm
untuk membandingkan daftar file yang diurutkan dan nama file memiliki spasi di dalamnya, meskipun mengutip variabel itu tidak berfungsi. Kemudian saya melihat cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html dan solusi pengaturan $ IFS dengan IFS = $ (echo -en "\ n \ b") bekerja untuk saya.Ini berfungsi dan lebih sederhana:
Penghargaan untuk Rupa ( https://github.com/rupa/z ) untuk jawaban ini.
sumber
Selain mengutip yang tepat, Anda dapat meminta
find
untuk menggunakan pemisah NULL, dan kemudian membaca dan memproses hasilnya dalam satuwhile
lingkaranIni harus menangani nama file apa pun yang sesuai dengan POSIX - lihat
man find
sumber
sumber
Saya melakukan sesuatu seperti ini untuk menemukan file yang mungkin berisi spasi.
Bekerja seperti pesona :)
sumber
Sebagian besar jawaban di sini terputus jika ada karakter baris baru dalam nama file. Saya menggunakan bash lebih dari 15 tahun, tetapi hanya interaktif.
Dengan Python, Anda dapat menggunakan os.walk (): http://docs.python.org/2/library/os.html#os.walk
Dan modul tarfile: http://docs.python.org/2/library/tarfile.html#tar-examples
sumber
Saya pikir Anda mungkin lebih baik menggunakan
find
opsi -exec.Temukan kemudian jalankan perintah menggunakan system call, sehingga spasi dan baris baru dipertahankan (lebih seperti pipa, yang akan memerlukan mengutip karakter khusus). Perhatikan bahwa "tar -c" berfungsi apakah arsip sudah ada atau belum, dan (setidaknya dengan bash) baik {} maupun + perlu dikutip.
sumber
Seperti yang disarankan minerz029, Anda perlu mengutip perluasan
find
perintah. Anda juga perlu mengutip semua pergantian dari$FILE
dalam loop Anda.Perhatikan bahwa
$()
sintaksis lebih disukai daripada penggunaan backticks; lihat pertanyaan U&L ini . Saya juga menghapus[[
kata kunci dan menggantinya dengan[
perintah karena itu POSIX.sumber
[[
dan[
, tampaknya itu[[
lebih baru dan mendukung lebih banyak fitur seperti globbing dan pencocokan regex.[[
hanya dibash
, bukansh
[[
mendukung globbing. Menurut wiki Greg , tidak ada globbing yang terjadi di dalam[[
.[ "ab" == a? ] && echo "true"
kemudian[[ "ab" == a? ]] && echo "true"
a*
berarti "diikuti oleh sejumlah karakter" daripada "semua file yang namanya dimulai dengana
dan memiliki sejumlah karakter sesudahnya". Coba[ ab = a* ] && echo true
vs[[ ab == a* ]] && echo true
..[[
masih melakukan ekspresi reguler sementara[
tidak. Pasti bingung