Быстро и грязно с GNU sed, при условии, что ни одна из ваших строк не имеет пробелов в конце:
$ sed -E -e 's/\s+/\|/4g' -e '1s/\S*$/info/' file
sample_1 sample_2 sample_3 info
52 59 80 wild|animal|herbe|small
25 65 71 pet|insect
Если в строках есть пробелы в конце, вы можете сначала удалить их:
sed -E -e 's/ +$//' -e 's/\s+/\|/4g' -e '1s/\S*$/info/' file
Менее элегантен, чем zmv
, но достаточно простогоfor
-цикла:
#!/bin/bash
for letter in {a..z} {A..Z} ; do
mkdir /path/to/dest/$letter
mv /path/to/source/*/${letter}?* /path/to/dest/$letter
done
Немного более эффективная версия, которая перебирает только те буквы и цифры, которые действительно присутствуют:
for file in *; do
if [[ ! -d "$file" ]]; then
firstLetter=${file:0:1}
mkdir -p "$firstLetter"
mv -- "$file" "$firstLetter"/
fi
done
Однако это не удастся, если у вас есть файл с тем же именем, что и у одного из каталогов. Например, файл с именем a
не позволит вам создать каталог с таким же именем a
. Чтобы обойти это, вы можете сделать:
tmpDir=$(mktemp -p "." -d)
for file in *; do
if [[ ! -d "$file" ]]; then
firstLetter=${file:0:1};
## If a file exists with this name
if [[ -e "$firstLetter" && ! -d "$firstLetter" ]]; then
## move the file to the tmp dir and update the value
## of the $file variable to point to it
mv -- "$file" "$tmpDir"
file="$tmpDir/$file"
fi
mkdir -p "$firstLetter";
mv -- "$file" "$firstLetter"/;
fi
done
# $tmpDir should be empty by now
rmdir "$tmpDir"