英文:
How can move the file and change the file extension with simple bash?
问题
在我的当前目录中选择包含`sqlite`的文件:
ls | grep sqlite
null and empty string in sqlite.txt
pythoin write None into sqlite.txt
将它们移动到`/tmp`目录:
ls |grep sqlite |xargs -i mv {} /tmp
ls /tmp | grep sqlite
null and empty string in sqlite.txt
pythoin write None into sqlite.txt
如何将它们移动到`/tmp`并同时将文件扩展名更改为`rst`?
ls |grep sqlite | some_simple_bash_command
执行后:
ls /tmp | grep sqlite
null and empty string in sqlite.rst
pythoin write None into sqlite.rst
@David C. Rankin,`grep sqlite *`根本无法工作!
英文:
Select file which contains sqlite in my current directory:
ls | grep sqlite
null and empty string in sqlite.txt
pythoin write None into sqlite.txt
Move them into /tmp directory:
ls |grep sqlite |xargs -i mv {} /tmp
ls /tmp | grep sqlite
null and empty string in sqlite.txt
pythoin write None into sqlite.txt
How can move them into /tmp and change the file extension as rst at the same time?
ls |grep sqlite | some_simple_bash_command
After executing it:
ls /tmp | grep sqlite
null and empty string in sqlite.rst
pythoin write None into sqlite.rst
@David C. Rankin,grep sqlite * can't work at all!
答案1
得分: 1
尝试这个 Shellcheck- 清理的代码:
for f in *sqlite*; do
mv -v -- ""$f"" ""/tmp/${f%.*}.rst""
done
*sqlite*展开为当前目录中文件名中包含字符串sqlite的文件列表。参见 Pattern Matching 部分的 Bash 参考手册。${f%.*}展开为$f的值,去除任何后缀。参见 删除字符串的一部分 (BashFAQ/100 (我如何在 bash 中进行字符串操作?))。--是传递给mv的参数,以确保正确处理文件名以-开头的文件。参见 Bash 陷阱 #2 (cp $file $target)。
英文:
Try this Shellcheck-clean code:
for f in *sqlite*; do
mv -v -- "$f" "/tmp/${f%.*}.rst"
done
*sqlite*expands to the list of files in the current directory that contain the stringsqliteanywhere in their names. See the Pattern Matching section of the Bash Reference Manual.${f%.*}expands to the value of$fwith any suffix removed. See Removing part of a string (BashFAQ/100 (How do I do string manipulation in bash?)).- The
--argument tomvis to ensure proper handling of files whose names begin with-. See Bash Pitfalls #2 (cp $file $target).
答案2
得分: 0
这是您要翻译的文本:
"Let's expand on the comment a bit. First, learn not to pipe ls to the utility you want to use. All utilities that operate on files will accept a list of filenames through file-globbing. So to grep all files in the present working directory containing "sqlite" it's just:
$ grep 'sqlite' *
To change a filename extension POSIX provides a parameter expansion with substring removal that allows you to trim from the right, e.g. ${var%pattern}, to trim to the last occurrence of pattern beginning from the right it is ${var%%pattern}. Note: pattern can contain normal file-globbing such as ? or *.
To trim from the left it is ${var#pattern} and ${var##pattern}, respectively. These are POSIX expansions meaning they are available in all POSIX shells. Bash on the other hand provides many, many more expansions (stuff between ${...}) that only work in bash (referred to as "bashisms") Use POSIX when available to solve your problem for maximum portability.
To change the extension of a filename stored in the variable "$f", it would be:
mv "$f" "${f%.old}.new"`
Where old and new are the old and new file extensions.
When you want to rename or move and rename all files that result from a glob selection (e.g. using pattern* or the like, a for loop is what you need, e.g to select all files in the current directory whose name begins with pattern you can use pattern* in
for f in pattern*; do
printf "%s\n" "$f"
done
(which simply prints the filename)
To move all files beginning with pattern to the /tmp directory, it would be:
for f in pattern*; do
mv "$f" /tmp
done
(note: xargs would do just fine here)
When you want to process files that are the result of running some other process or utility, bash provides process substitution allowing you to feed a while loop in the form of while read -r var; do #stuff with "$var"; done < <(process). In your example of grep sqlite to move all files returned to /tmp while changing the extension from old to new, that would be:
while read -r f; do
mv "$f" "/tmp/${f%.old}.new"
done < <(grep 'sqlite' *)
(for POSIX shells you would pipe the result of grep to your while loop, e.g. grep 'sqlite' * | while read -r f ...)
Look things over and let me know if you have questions or if I missed the intent of your question."
英文:
Let's expand on the comment a bit. First, learn not to pipe ls to the utility you want to use. All utilities that operate on files will accept a list of filenames through file-globbing. So to grep all files in the present working directory containing "sqlite" it's just:
$ grep 'sqlite' *
To change a filename extension POSIX provides a parameter expansion with substring removal that allows you to trim from the right, e.g. ${var%pattern}, to trim to the last occurrence of pattern beginning from the right it is ${var%%pattern}. Note: pattern can contain normal file-globbing such as ? or *.
To trim from the left it is ${var#pattern} and ${var##pattern}, respectively. These are POSIX expansions meaning they are available in all POSIX shells. Bash on the other hand provides many, many more expansions (stuff between ${...}) that only work in bash (referred to as "bashisms") Use POSIX when available to solve your problem for maximum portability.
To change the extension of a filename stored in the variable "$f", it would be:
mv "$f" "${f%.old}.new"`
Where old and new are the old and new file extensions.
When you want to rename or move and rename all files that result from a glob selection (e.g. using pattern* or the like, a for loop is what you need, e.g to select all files in the current directory whose name begins with pattern you can use pattern* in
for f in pattern*; do
printf "%s\n" "$f"
done
(which simply prints the filename)
To move all files beginning with pattern to the /tmp directory, it would be:
for f in pattern*; do
mv "$f" /tmp
done
(note: xargs would do just fine here)
When you want to process files that are the result of running some other process or utility, bash provides process substitution allowing you to feed a while loop in the form of while read -r var; do #stuff with "$var"; done < <(process). In your example of grep sqlite to move all files returned to /tmp while changing the extension from old to new, that would be:
while read -r f; do
mv "$f" "/tmp/${f%.old}.new"
done < <(grep 'sqlite' *)
(for POSIX shells you would pipe the result of grep to your while loop, e.g. grep 'sqlite' * | while read -r f ...)
Look things over and let me know if you have questions or if I missed the intent of your question.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。



评论