我是 bash 的新手,我认为在 xargs 中使用变量时遇到了问题。
imanuel@orangepipc:~$ find /media/et10000 -name '*' -exec file {} \; | grep -o -P '^.+: \w+ image' | cut -d':' -f1 | xargs -I {} sh -c "fname="{}"; echo 'filename:'; echo $fname; filebase=$(basename $fname); filenew=${fname:14}; mkdir --parents /media/newhdd/photos$(dirname $fnamenew); cp -dv $fname /media/newhdd/photos$fnamenew; ln -s /media/newhdd/photos/year/$(date +%Y)/$fnamebase /media/newhdd/photos$fnamenew"
我拍每张照片时都会出现这个错误,直到我按下 ^C。
filename:
mkdir: cannot create directory ‘/home/imanuel/photos’: File exists
cp: missing destination file operand after ‘/home/imanuel/photos’
Try 'cp --help' for more information.
ln: failed to create symbolic link ‘/home/imanuel/photos/2016’: File exists
因此,问题是无论我怎么尝试,fname 变量似乎都无法设置。我尝试在 {} 和 $fname 周围加上双引号,并将外面的两个双引号替换为 '。
答案1
我不确定您是否使用 xarg,但可能像往常一样有很多种方法可以到达罗马。这里是我的方法示例:
/bin/bash #!/bin/bash SRCDIR="$HOME/Pictures/." # 应为:/media/et10000 DST="." # 应为:/media/newhdd/photos 查找 ${SRCDIR} -type f -exec file {} \; | grep -o -P'^.+:\w+ image' | cut -d':' -f1|while read fname 做 回显“文件:${fname}” 文件库=$(目录名 $fname); filenew=$(basename"$fname"); echo "文件新文件:${文件新文件}" ## 将所有 mkdir、复制和链接放在此处,但请注意 ## 空格和其他字符需要被屏蔽 - 因此请将您的 ## 变量的确切位置:“${varname}” ## ln -s "/media/newhdd/photos/year/$(date +%Y)/${fnamebase}" 回显“---” 完毕
答案2
OP 使用双引号作为 的参数sh -c
,这会导致父 shell 进行变量和命令替换。例如,"...; echo $fname; ..."
将被父 shell 替换为 ,"...; echo ; ..."
因为父 shell 不知道$fname
。
如果您坚持使用xargs
(而不是while read -r line
),我建议对最外层的引用级别使用单引号,对下一层引用级别使用双引号,然后\"
在需要时对第三层引用级别使用双引号。
答案3
我修复了 all-in-one 命令。然后我将其转换为 bash 脚本。不过,欢迎提出任何使其更具可读性的建议。:D
#!/bin/sh
find "$1" -name '*' -exec file {} \; | grep -o -P '^.+: \w+ image' | cut -d':' -f1 | xargs -I {} sh -c "fname={}; filebase=\$(basename \$fname); fnamenew=\${fname#$1}; mkdir --parents /media/newhdd/photos\$(dirname \$fnamenew); cp -dv \$fname /media/newhdd/photos\$fnamenew; mkdir --parents /media/newhdd/photos/year/\$(date +%Y); ln -fs /media/newhdd/photos\$fnamenew /media/newhdd/photos/year/\$(date +%Y)/\$fnamebase; mkdir --parents /media/newhdd/photos/year/\$(date +%Y/%m-%B); ln -fs /media/newhdd/photos\$fnamenew /media/newhdd/photos/year/\$(date +%Y/%m-%B)/\$fnamebase;"
脚本的主要问题如下:
- 我没有避开美元符号,因此我将每个
$
符号都替换为\$
。 - 我意外地输入了 filenew 而不是 fnamenew,并且 Dash(Debian Almquist Shell)中没有子字符串功能,因此我将
filenew=\${fname:14};
其改为fnamenew=\${fname#$1};
。 - 我原本在 {} 两边加上了双引号,但那是打字错误。:)