Если у вас достаточно свежая версия GNU awk (gawk
), вы можете
awk -i inplace -F'/' '$7 == "_f" {print > "otherfile"; next} 1' file
Если ваш awk не поддерживает параметр -i inplace
, вы можете сделать то же самое, но перенаправить вывод во временный файл, а затем переименовать его.
Это из-за этой строчки:
ls backup 2>/dev/null
вы перенаправляете только stderr, но не stdout. Вы должны сделать это:
ls backup >/dev/null 2>&1 || mkdir backup
или просто:
mkdir -p backup
Вы также должны позаботиться обо всех предупреждениях, выдаваемых shellcheck:
$ shellcheck./p.sh
In./p.sh line 18:
read answer
^--^ SC2162: read without -r will mangle backslashes.
In./p.sh line 24:
mv $name backup
^---^ SC2086: Double quote to prevent globbing and word splitting.
Did you mean:
mv "$name" backup
For more information:
https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing...
https://www.shellcheck.net/wiki/SC2162 -- read without -r will mangle backs...
Поскольку вы делаете ls backup 2>/dev/null
для каждого файла, перемещенного в каталог backup
, следующий ls
покажет их;
кстати, весь ваш скрипт можно заменить одной командой rsync
ниже:
rsync --include='*.{txt,csv,xyz}' /path/to/source/* /path/to/backup/
см.man rsync
для получения подробной информации, а также о том, как вы можете удалить после синхронизации.
Если бы bash был разрешен, я бы сделал так:
#!/usr/bin/env bash
if (( $# == 0 )); then
echo "usage: ${0##*/} extension..." >&2
exit 1
fi
dir=./backup
mkdir -p "$dir"
# if the script is called like `script.sh foo bar baz`
# then $pattern is `@(*foo|*bar|*baz)`
pattern=$(
set -- "${@/#/*}"
IFS='|'
echo "@($*)"
)
shopt -s nocasematch
for file in *; do
# right-hand side is specifically unquoted
if [[ "$file" == $pattern ]]; then
read -p "Move file '$file'? [y/N] " ans
if [[ "$ans" == Y* ]]; then
mv -i -v "$file" "$dir"
fi
fi
done
Поскольку это задание, проведите некоторое исследование любой части, которую вы не понимаете, прежде чем задавать здесь конкретные вопросы. Руководство bash — хорошее место для начала.