Bu yanıtın her tür dosya için çözümü vardır . Yeni satırlar veya boşluklarla.
Son bash, antik bash ve hatta eski posix kabukları için çözümler var.
Bu cevapta [1] aşağıda listelenen ağaç testler için kullanılır.
seçmek
select
Bir dizi ile çalışmak kolaydır :
$ dir='deep/inside/a/dir'
$ arr=( "$dir"/* )
$ select var in "${arr[@]}"; do echo "$var"; break; done
Veya konumsal parametrelerle:
$ set -- "$dir"/*
$ select var; do echo "$var"; break; done
Bu nedenle, tek gerçek sorun, bir dizinin içinde veya Konumsal Parametrelerin içinde "dosya listesini" (doğru bir şekilde ayrılmış) almaktır. Okumaya devam et.
darbe
Bash ile bildirdiğiniz sorunu görmüyorum. Bash belirli bir dizinde arama yapabilir:
$ dir='deep/inside/a/dir'
$ printf '<%s>\n' "$dir"/*
<deep/inside/a/dir/directory>
<deep/inside/a/dir/file>
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/zz last file>
Veya bir döngüden hoşlanıyorsanız:
$ set -- "$dir"/*
$ for f; do printf '<%s>\n' "$f"; done
<deep/inside/a/dir/directory>
<deep/inside/a/dir/file>
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/zz last file>
Yukarıdaki sözdiziminin herhangi bir (makul) kabukla (en az csh değil) düzgün çalışacağını unutmayın.
Yukarıdaki sözdiziminin sahip olduğu tek sınır diğer dizinlere inmektir.
Ama bash bunu yapabilirdi:
$ shopt -s globstar
$ set -- "$dir"/**/*
$ for f; do printf '<%s>\n' "$f"; done
<deep/inside/a/dir/directory>
<deep/inside/a/dir/directory/file>
<deep/inside/a/dir/directory/file name>
<deep/inside/a/dir/directory/file with a
newline>
<deep/inside/a/dir/directory/zz last file>
<deep/inside/a/dir/file>
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/zz last file>
(Bu olanlar gibi sadece bazı dosyaları seçmek için uç sadece * yerine dosyada):
$ set -- "$dir"/**/*file
$ printf '<%s>\n' "$@"
<deep/inside/a/dir/directory/file>
<deep/inside/a/dir/directory/zz last file>
<deep/inside/a/dir/file>
<deep/inside/a/dir/zz last file>
güçlü
Eğer bir "uzay yerleştirdiğinizde kasa başlığında", ne demek istediğini "olduğunu varsaymak gidiyorum sağlam ".
Boşluklara (veya yeni satırlara) karşı sağlam olmanın en basit yolu, boşluklara (veya yeni satırlara) sahip girdilerin işlenmesini reddetmektir. Kabukta bunu yapmanın çok basit bir yolu, herhangi bir dosya adı boşlukla genişlerse hata ile çıkmaktır. Bunu yapmanın birkaç yolu vardır, ancak en kompakt (ve posix) (ancak ani dizin adları ve nokta dosyalarından kaçınmak da dahil olmak üzere bir dizin içeriğiyle sınırlıdır):
$ set -- "$dir"/file* # read the directory
$ a="$(printf '%s' "$@" x)" # make it a long string
$ [ "$a" = "${a%% *}" ] || echo "exit on space" # if $a has an space.
$ nl='
' # define a new line in the usual posix way.
$ [ "$a" = "${a%%"$nl"*}" ] || echo "exit on newline" # if $a has a newline.
Kullanılan çözelti bu maddelerden herhangi birinde sağlamsa testi kaldırın.
Bash'de, alt dizinler yukarıda açıklanan ** ile bir kerede test edilebilir.
Nokta dosyalarını dahil etmenin birkaç yolu vardır, Posix çözümü:
set -- "$dir"/* "$dir"/.[!.]* "$dir"/..?*
bulmak
Bulun herhangi bir nedenden dolayı kullanılması gerekiyorsa, ayırıcıyı bir NUL (0x00) ile değiştirin.
bash 4.4+
$ readarray -t -d '' arr < <(find "$dir" -type f -name file\* -print0)
$ printf '<%s>\n' "${arr[@]}"
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/directory/file name>
<deep/inside/a/dir/directory/file with a
newline>
<deep/inside/a/dir/directory/file>
<deep/inside/a/dir/file>
bash 2.05+
i=1 # lets start on 1 so it works also in zsh.
while IFS='' read -d '' val; do
arr[i++]="$val";
done < <(find "$dir" -type f -name \*file -print0)
printf '<%s>\n' "${arr[@]}"
POSIXLY
Bulmanın bir NUL sınırlayıcısının bulunmadığı ve okuma için -d
(veya -a
) bulunmayan geçerli bir POSIX çözümü yapmak için tamamen farklı bir yaklaşım gerekiyor.
-exec
Bulmaktan bir kabuğa çağrı ile bir kompleks kullanmamız gerekir :
find "$dir" -type f -exec sh -c '
for f do
echo "<$f>"
done
' sh {} +
Veya, gerekli olan bir seçimse (select sh yerine bash'ın bir parçasıdır):
$ find "$dir" -type f -exec bash -c '
select f; do echo "<$f>"; break; done ' bash {} +
1) deep/inside/a/dir/file name
2) deep/inside/a/dir/zz last file
3) deep/inside/a/dir/file with a
newline
4) deep/inside/a/dir/directory/file name
5) deep/inside/a/dir/directory/zz last file
6) deep/inside/a/dir/directory/file with a
newline
7) deep/inside/a/dir/directory/file
8) deep/inside/a/dir/file
#? 3
<deep/inside/a/dir/file with a
newline>
[1] Bu ağaç (\ 012 yeni satırlardır):
$ tree
.
└── deep
└── inside
└── a
└── dir
├── directory
│ ├── file
│ ├── file name
│ └── file with a \012newline
├── file
├── file name
├── otherfile
├── with a\012newline
└── zz last file
Bu iki komutla oluşturulabilir:
$ mkdir -p deep/inside/a/dir/directory/
$ touch deep/inside/a/dir/{,directory/}{file{,\ {name,with\ a$'\n'newline}},zz\ last\ file}