Understanding the line that calls the file name - perl

I do not understand the line that calls the file name.
#!/bin/sh
cd Desktop/Test/xml_replace
find . -name "*.xml" -print | while IFS= read -r file; do echo "$file"
perl -pi -e 's/&/&/' $file

Related

How to exclude symlink files from find command?

I use the following command to do some processing on text files,however it changes the symlink files aswell,is there a way to exclude symlink files from the find command and include only the actual files?
find . \( -name "*.txt" ! -name "release.txt" \) | xargs -t -n1 sed -i '' -e '/^#/d;/^nocrc=/d;/acaddr=/d;/^$/d;s/[ \t]*$//'

Files With Spaces Are Treated As Seperate Files

How can I modify the script to not treat files with spaces as separate files?
thetime=`date +%Y-%m-%d_%H:%M:%S` #
for i in $(find . ! -name "*.filepart")
do
extn=${i##*.} # save the extension of the file
mv "$i" "${i%.*}"$(date "+_%Y-%m-%d_%H:%M:%S.${extn}")
done
mv: cannot stat ‘./user1/upload/Axle’: No such file or directory
mv: cannot stat ‘Assy’: No such file or directory
mv: cannot stat ‘Removal.doc’: No such file or directory
#find . ! -name "*.filepart"
#./user1/upload/Axle Assy Removal.doc
This won't work with files whose names contain whitespace:
for i in $(find . ! -name "*.filepart"); do # Fail
The following two methods will work for all file names:
Method 1: Use -execdir
find . -type f ! -name "*.filepart" -execdir sh -c 'f=$(basename "$1"); mv "./$f" "./${f%.*}$(date "+_%Y-%m-%d_%H:%M:%S")${f#${f%.*}}"' Mv {} \;
Method 2: Use -print0
find . -type f ! -name "*.filepart" -print0 | while IFS= read -r -d $'\0' file
do
d=$(dirname "$file")
f=${file#$d}
mv "$d$f" "$d${f%.*}$(date "+_%Y-%m-%d_%H:%M:%S")${f#${f%.*}}"
done
Further reading
How can I find and safely handle file names containing newlines, spaces or both?

Replace a given string in folders throughout a directory

I want to do the equivalent of this, but [maybe recursively] for all, say, .md files within a directory tree.
perl -pi -e 's/FOO/BAR/g' *.md
Use find:
find /path -name "*.md" -exec perl -pi -e 's/FOO/BAR/g' {} \;
A simple & pure bash one line solution by using bash parameter expansion:
$ cd ~/
$ mkdir test
$ cd test/
$ touch foo{1..10}.md
$ ls
foo1.md foo10.md foo2.md foo3.md foo4.md foo5.md foo6.md foo7.md foo8.md foo9.md
$ for file in ./*.md; do mv "$file" "${file/foo/bar}"; done
$ ls
bar1.md bar10.md bar2.md bar3.md bar4.md bar5.md bar6.md bar7.md bar8.md bar9.md
Of course it can be combined with find as suggested by devnull:
$ files=($(find ./test -name "*.md"))
$ for file in "${files[#]}"; do mv "$file" "${file/foo/bar}"; done
Or pipe the ouptut of find to the loop:
$ find ./test -name "*.md" | for file in $(xargs -0); do mv "$file" "${file/foo/bar}"; done

How can I check whether a piped content is text with perl

I've written a svn-hook for text files. The content test looks like this:
svnlook cat -t $txn $repos $file 2>/dev/null | file - | egrep -q 'text$'
and I was wondering if this could be done with Perl. However something like this doesn't work:
svnlook cat -t $txn $repos $file 2>/dev/null | perl -wnl -e '-T' -
I'm testing the exit status of this invocation ($?) to see if the given file was text or binary. Since I'm getting the content out of svn. I can't use perl's normal file check.
I've done a simulation with the file program and perl with a text and binary file (text.txt, icon.png):
find -type f | xargs -i /bin/bash -c 'if $(cat {} | file - | egrep -q "text$"); then echo "{}: text"; else echo "{}: binary"; fi'
./text.txt: text
./icons.png: binary
find -type f | xargs -i /bin/bash -c 'if $(cat {} | perl -wln -e "-T;"); then echo "{}: text"; else echo "{}: binary"; fi'
./text.txt: text
./icons.png: text
You're testing perl's exit code, but you never set it. You need
perl -le'exit(-T STDIN ?0:1)' < file

Use grep / sed for filename search & replace?

I have a bunch of image files that were incorrectly named 'something#x2.png' and they need to be 'something#2x.png'. They're spread across multiple directories like so:
/images
something#x2.png
/icons
icon#x2.png
/backgrounds
background#x2.png
How can I use grep + sed to find/replace as needed?
Ruby(1.9+)
$ ruby -e 'Dir["**/*#x2.png"].each{|x| File.rename( x, x.sub(/#x2/,"#2x") ) }'
Look at qmv and rename
find -iname '*.png' -print0 | xargs -0 qmv -d
will launch your default editor and allow you to interactively edit the names
rename s/#x2/#2x/ *.png
Slashes look linuxy/unixoid to me. Do you have find and rename?
find -name "*#x2*" -execdir rename 's/#x2/#2x/' {} +
rename is worth installing, comes in some perl-package.
With bash 2.x/3.x
#!/bin/bash
while IFS= read -r -d $'\0' file; do
echo mv "$file" "${file/#x2/#2x}"
done < <(find images/ -type f -name "something*#x2*.png" -print0)
With bash 4.x
#!/bin/bash
shopt -s globstar
for file in images/**; do
[[ "$file" == something*#x2*.png ]] && echo mv "$file" "${file/#x2/#2x}"
done
Note:
In each case I left in an echo so you can do a dry-run, remove the echo if the output is sufficient