bash/zsh/ksh でのコピー中にディレクトリを作成するにはどうすればよいですか?
-
13-09-2019 - |
質問
たとえば、dev ファイルを master ブランチにコピーするときに、次のメッセージが頻繁に表示されます。
cp: /Users/Masi/gitHub/shells/zsh/dvorak: No such file or directory
cp: /Users/Masi/gitHub/shells/zsh/dvorak2: No such file or directory
指定されたフォルダーの作成について質問され、質問に「はい」と答えると最初のコマンドが実行されるようにしたいと考えています。
存在しないディレクトリにファイルをコピーしようとしたときの疑似コードでの試み
if no such a directory exists, then asks users about to create it:
if yes, then mkdir directory AND run the initial command again
else do noting
問題点
- 警告メッセージを変更するには: 「そのようなファイルまたはディレクトリはありません」コマンドを制御するファイルはどれですか?
- 最初のコマンドのパスとファイルなしの mkidr パスをスクレイピングするには:最初のコマンドでパスをスクレイピングするにはどうすればよいでしょうか?
- AWK などの選択した言語で最後からスクレイピングするには: / がフィールド区切り文字である場合、パス内の最後の一致をどのように削除しますか? AWK で文字を端からスクレイピングする方法がわかりません。
解決
ここでzshのは、bashまたはkshで動作します、私が書いた関数である。
注: のそれが有効になってデバッグが(それがそれらを実行するのではなく、実行するコマンドをエコー)しています。あなたがその行をコメントアウトした場合、それは実際にそれらを実行します。の
の注意ののそれは徹底的にテストされていないの
。 cpmd
/usr/local/bin
中(または他の場所で、あなたのパスに)と呼ばれるファイルにこのスクリプトを入れて、それを使用します。次のコマンドを入力(または起動スクリプトに追加 - bashのためにそれを~/.bashrc
されるだろう)シェルプロンプトから、それを有効にするには:
source cpmd
次に、あなたは、このようなコマンドを使用してファイルをコピーすることができます:
cpmd carparts /home/dave/Documents/nonexistent/newdir/
どちらのディレクトリ「存在しない」または「newdirが」まだ存在しています。両方のディレクトリは「carparts」という名前のファイルが「newdirを」にコピーされ、その後に作成されます。
あなたが最後にスラッシュ(「/」)が含まれていない場合はそれが作成される前に、最後の部分は、ファイル名と任意の実在しないディレクトリとして扱われます:
cpmd supplies /home/dave/Documents/anothernew/consumables
ディレクトリ「anothernew」、その後に作成される「電源が」新しいファイル名「消耗品」とコピーされます。
先のすべてのディレクトリがすでに存在する場合は、、cpmd
は、通常のcp
コマンドのように動作します。
function cpmd {
# copies files and makes intermediate dest. directories if they don't exist
# for bash, ksh or zsh
# by Dennis Williamson - 2009-06-14
# http://stackoverflow.com/questions/993266/unable-to-make-nosuchdirectory-message-useful-in-zsh
# WARNING: no validation is performed on $1 and $2
# all cp commands below are hardcoded with -i (interactive) to prevent overwriting
if [[ -n $KSH_VERSION ]]
then
alias local=typeset
local func="$0"
local lastchar="${2: -1}"
readcmd () { read "$2?$1"; }
elif [[ -n $ZSH_VERSION ]]
then
local func="$0"
# the following two lines are split up instead of doing "${2[-1]}"
# to keep ksh from complaining when the function is loaded
local dest="$2"
local lastchar="${dest[-1]}"
readcmd () { read "$2?$1"; }
elif [[ -n $BASH_VERSION ]]
then
local func="$FUNCNAME"
local lastchar="${2:(-1)}"
readcmd () { read -p "$1" $2; }
else
echo "cpmd has only been tested in bash, ksh and zsh." >&2
return 1
fi
local DEBUG='echo' # COMMENT THIS OUT to make this function actually work
if [[ ${#@} != 2 ]]
then
echo "$func: invalid number of parameters
Usage:
$func source destination
where 'destination' can include nonexistent directories (which will
be created). You must end 'destination' with a / in order for it to
specify only directories. Without the final slash, the 'source' will
be copied with a new name (the last portion of 'destination'). If you
are copying multiple files and 'destination' is not a directory, the
copy will fail." >&2
return 1
fi
local dir=$(dirname "$2")
local response
local nl=$'\n'
# destination ($2) is presumed to be in one of the following formats:
# .../existdir test 1 (-d "$2")
# .../existdir/existfile test 2 (-f "$2")
# .../existdir/newfile test 3 (-d "$dir" && $lastchar != '/')
# .../existdir/newdir/ (else)
# .../newdir/newdir/ (else)
# .../newdir/newfile (else)
if [[ -d "$2" || -f "$2" || (-d "$dir" && $lastchar != '/') ]]
then
$DEBUG cp -i "$1" "$2"
else
if [[ $lastchar == '/' ]]
then
dir="$2"
fi
local prompt="$func: The destination directory...${nl} ${dir}${nl}...does not exist. Create? (y/n): "
while [[ -z $response ]]
do
readcmd "$prompt" response
case $response in
y|Y) response="Y" ;;
n|N) ;;
*) response=
prompt="$func: Invalid response.${nl} Create destination directory? (y/n): ";;
esac
done
if [[ $response == "Y" ]]
then
$DEBUG mkdir -p "$dir" && $DEBUG cp -i "$1" "$2"
else
echo "$func: Cancelled." >&2
fi
fi
}
他のヒント
というエラーメッセージがcp
コマンドではなく、zshのから来ています。あなたは出力を改善したい場合、あなたは切り捨て、それが存在するかどうかを確認するためにチェックするとともに、パスを検査するためのロジックを記述する必要があるとしている。
これを支援するためのコマンドは、ベース名を見てそこに持っている(1)とのdirname(1)。