How to compare two files and if found equal ask the user to delete duplicate file by using shell script?
up vote
2
down vote
favorite
I am learning linux and was given this problem as my homework but i can't solve this that how we can compare two files content in shell mode.
(Here, we can assume that both files having text content like this
for eg.
$cat > f1
this is file 1)
$ cat duplicate_file.sh
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
x=` wc newfile | cut -d" " -f2 `
if [` $x -eq 0 `]
then
rm -i $file2
fi
I made this program but this ain't working!! So, Any suggestions??
shell-script files
New contributor
add a comment |
up vote
2
down vote
favorite
I am learning linux and was given this problem as my homework but i can't solve this that how we can compare two files content in shell mode.
(Here, we can assume that both files having text content like this
for eg.
$cat > f1
this is file 1)
$ cat duplicate_file.sh
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
x=` wc newfile | cut -d" " -f2 `
if [` $x -eq 0 `]
then
rm -i $file2
fi
I made this program but this ain't working!! So, Any suggestions??
shell-script files
New contributor
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I am learning linux and was given this problem as my homework but i can't solve this that how we can compare two files content in shell mode.
(Here, we can assume that both files having text content like this
for eg.
$cat > f1
this is file 1)
$ cat duplicate_file.sh
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
x=` wc newfile | cut -d" " -f2 `
if [` $x -eq 0 `]
then
rm -i $file2
fi
I made this program but this ain't working!! So, Any suggestions??
shell-script files
New contributor
I am learning linux and was given this problem as my homework but i can't solve this that how we can compare two files content in shell mode.
(Here, we can assume that both files having text content like this
for eg.
$cat > f1
this is file 1)
$ cat duplicate_file.sh
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
x=` wc newfile | cut -d" " -f2 `
if [` $x -eq 0 `]
then
rm -i $file2
fi
I made this program but this ain't working!! So, Any suggestions??
shell-script files
shell-script files
New contributor
New contributor
New contributor
asked Nov 10 at 6:13
Hariom kushwaha
111
111
New contributor
New contributor
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
up vote
4
down vote
The immediate issue in your code is the syntax error on the line reading
if [` $x -eq 0 `]
The [
and ]
must be separated from the arguments within by a space character. Also, the command substitution on this line, `$x -eq 0`
, is nonsensical as it would try to run the value of $x
as a command.
You also have issues with non-quoting of your variable expansions, which disqualifies your script from working on filenames containing whitespace characters and filename globbing patterns.
The script also unconditionally clobbers the file newfile
needlessly (and would fail if newfile
was the name of an existing directory) and it lacks a #!
-line.
There is no point in asking the user interactively for file paths. It would be better for the user to be able to make use of the shell's filename completion on the command line and provide the pathnames to the files there as two operands:
$ ./script.sh some/path/file1 some/other/path/file2
If running the script in this way, the two pathnames will be available inside the script as "$1"
and "$2"
.
The cmp
utility can be used in this script without creating a temporary file. Instead of redirecting its output, make it quiet by using its -s
option (for "silent") and use its exit status to determine if the two files were identical or not.
The script would look like
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
Or, shorter,
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
This would call rm -i
on the second of the two given pathnames if it referred to a file with identical contents as the first pathname. The --
in the cmp
and rm
commands is necessary to avoid interpreting a filename starting with a dash as a set of options.
The issue with this script, as with your own script, is that if you give it the same pathname twice, i.e. you compare a file against itself, then it will offer to remove it.
Therefore, we also need to make sure that the two pathnames refer to two different files.
You can do that by comparing the two pathname strings with each other:
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
This may be enough for most applications but does not take symbolic links into account. In some shells you can also use the non-standard -ef
test ("equal file") which tests whether two pathnames refer to the same file (same i-node number and device):
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
or,
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
And with some sanity checks (also moving the -ef
test to the sanity checks section):
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:nt%s file1 file2n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same filen' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
Note that quoting the variable expansions is important since it's not uncommon for pathnames to contain spaces (on macOS, this is very common). Double quoting variable expansions also stops them from being interpreted as shell globbing patterns (your code would, for example, not work on a file called *
). Also note the use of a #!
-line appropriate for the script.
If your homework assignment requires you to read the pathnames of the two files interactively, then do that with read -r
and with IFS
set to an empty string. This would allow you to read pathnames starting with whitespace characters and containing characters:
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same filen' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
Related:
- Why does my shell script choke on whitespace or other special characters?
- Understanding "IFS= read -r line"
- ShellCheck.net
If you at some point need to check whether a file is empty, as in your own code, then don't call wc
on it (it is inefficient as it would have to read the whole file). Instead, use a -s
test:
if [ -s "$pathname" ]; then
printf '%s has non-zero sizen' "$pathname"
else
printf '%s is empty (or does not exist)n' "$pathname"
fi
See man test
on your system, or refer to the POSIX standard for this utility.
did U&L recently started offering Code Review tasks?
– iBug
Nov 10 at 13:50
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
Nov 10 at 14:07
add a comment |
up vote
3
down vote
First include shebang #!
at the top like #!/bin/bash
You are having two errors:
Instead of
cmp $file1 $file2 > newfile,
it should be
cmp -- "$file1" "$file2" > newfile
as these values of these variables may have spaces, tabs, newline (characters of $IFS
), *
, [
, ?
(wildcard characters) in them or may start with -
.
Second error:
Instead of
if [` $x -eq 0 `]
it should be
if [ "$x" -eq 0 ].
Otherwise you will get error
bash: 0: command not found.
Also if you are having whitespace or wildcards in the file names then it should be:
rm -i -- "$file2"
otherwise it can delete multiple files.
add a comment |
up vote
0
down vote
There are many ways to solve this, but I'll go with what you've started.
First, don't forget the lead off the script with the interpreter string ("shebang"):
#!/bin/bash
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
At this point you could test a couple of things:
- if newfile is not empty the files differ
if [ ! -s newfile ]; then
rm -i $file2
fi
- Test the exit code for cmp operation. If it is 0, the files match.
if [ `echo $?` == 0 ]; then
rm -i $file2
fi
Also, your wc command isn't quite working. Try running it outside of the script. Do you get the result you're expecting?
I thinkwc
command is working, when I tested it, the problem is incmp $file1 $file2 > newfile
command.
– Debian_yadav
Nov 10 at 7:48
1
Why not test withif cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...
– Kusalananda
Nov 10 at 9:49
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
The immediate issue in your code is the syntax error on the line reading
if [` $x -eq 0 `]
The [
and ]
must be separated from the arguments within by a space character. Also, the command substitution on this line, `$x -eq 0`
, is nonsensical as it would try to run the value of $x
as a command.
You also have issues with non-quoting of your variable expansions, which disqualifies your script from working on filenames containing whitespace characters and filename globbing patterns.
The script also unconditionally clobbers the file newfile
needlessly (and would fail if newfile
was the name of an existing directory) and it lacks a #!
-line.
There is no point in asking the user interactively for file paths. It would be better for the user to be able to make use of the shell's filename completion on the command line and provide the pathnames to the files there as two operands:
$ ./script.sh some/path/file1 some/other/path/file2
If running the script in this way, the two pathnames will be available inside the script as "$1"
and "$2"
.
The cmp
utility can be used in this script without creating a temporary file. Instead of redirecting its output, make it quiet by using its -s
option (for "silent") and use its exit status to determine if the two files were identical or not.
The script would look like
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
Or, shorter,
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
This would call rm -i
on the second of the two given pathnames if it referred to a file with identical contents as the first pathname. The --
in the cmp
and rm
commands is necessary to avoid interpreting a filename starting with a dash as a set of options.
The issue with this script, as with your own script, is that if you give it the same pathname twice, i.e. you compare a file against itself, then it will offer to remove it.
Therefore, we also need to make sure that the two pathnames refer to two different files.
You can do that by comparing the two pathname strings with each other:
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
This may be enough for most applications but does not take symbolic links into account. In some shells you can also use the non-standard -ef
test ("equal file") which tests whether two pathnames refer to the same file (same i-node number and device):
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
or,
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
And with some sanity checks (also moving the -ef
test to the sanity checks section):
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:nt%s file1 file2n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same filen' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
Note that quoting the variable expansions is important since it's not uncommon for pathnames to contain spaces (on macOS, this is very common). Double quoting variable expansions also stops them from being interpreted as shell globbing patterns (your code would, for example, not work on a file called *
). Also note the use of a #!
-line appropriate for the script.
If your homework assignment requires you to read the pathnames of the two files interactively, then do that with read -r
and with IFS
set to an empty string. This would allow you to read pathnames starting with whitespace characters and containing characters:
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same filen' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
Related:
- Why does my shell script choke on whitespace or other special characters?
- Understanding "IFS= read -r line"
- ShellCheck.net
If you at some point need to check whether a file is empty, as in your own code, then don't call wc
on it (it is inefficient as it would have to read the whole file). Instead, use a -s
test:
if [ -s "$pathname" ]; then
printf '%s has non-zero sizen' "$pathname"
else
printf '%s is empty (or does not exist)n' "$pathname"
fi
See man test
on your system, or refer to the POSIX standard for this utility.
did U&L recently started offering Code Review tasks?
– iBug
Nov 10 at 13:50
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
Nov 10 at 14:07
add a comment |
up vote
4
down vote
The immediate issue in your code is the syntax error on the line reading
if [` $x -eq 0 `]
The [
and ]
must be separated from the arguments within by a space character. Also, the command substitution on this line, `$x -eq 0`
, is nonsensical as it would try to run the value of $x
as a command.
You also have issues with non-quoting of your variable expansions, which disqualifies your script from working on filenames containing whitespace characters and filename globbing patterns.
The script also unconditionally clobbers the file newfile
needlessly (and would fail if newfile
was the name of an existing directory) and it lacks a #!
-line.
There is no point in asking the user interactively for file paths. It would be better for the user to be able to make use of the shell's filename completion on the command line and provide the pathnames to the files there as two operands:
$ ./script.sh some/path/file1 some/other/path/file2
If running the script in this way, the two pathnames will be available inside the script as "$1"
and "$2"
.
The cmp
utility can be used in this script without creating a temporary file. Instead of redirecting its output, make it quiet by using its -s
option (for "silent") and use its exit status to determine if the two files were identical or not.
The script would look like
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
Or, shorter,
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
This would call rm -i
on the second of the two given pathnames if it referred to a file with identical contents as the first pathname. The --
in the cmp
and rm
commands is necessary to avoid interpreting a filename starting with a dash as a set of options.
The issue with this script, as with your own script, is that if you give it the same pathname twice, i.e. you compare a file against itself, then it will offer to remove it.
Therefore, we also need to make sure that the two pathnames refer to two different files.
You can do that by comparing the two pathname strings with each other:
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
This may be enough for most applications but does not take symbolic links into account. In some shells you can also use the non-standard -ef
test ("equal file") which tests whether two pathnames refer to the same file (same i-node number and device):
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
or,
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
And with some sanity checks (also moving the -ef
test to the sanity checks section):
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:nt%s file1 file2n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same filen' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
Note that quoting the variable expansions is important since it's not uncommon for pathnames to contain spaces (on macOS, this is very common). Double quoting variable expansions also stops them from being interpreted as shell globbing patterns (your code would, for example, not work on a file called *
). Also note the use of a #!
-line appropriate for the script.
If your homework assignment requires you to read the pathnames of the two files interactively, then do that with read -r
and with IFS
set to an empty string. This would allow you to read pathnames starting with whitespace characters and containing characters:
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same filen' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
Related:
- Why does my shell script choke on whitespace or other special characters?
- Understanding "IFS= read -r line"
- ShellCheck.net
If you at some point need to check whether a file is empty, as in your own code, then don't call wc
on it (it is inefficient as it would have to read the whole file). Instead, use a -s
test:
if [ -s "$pathname" ]; then
printf '%s has non-zero sizen' "$pathname"
else
printf '%s is empty (or does not exist)n' "$pathname"
fi
See man test
on your system, or refer to the POSIX standard for this utility.
did U&L recently started offering Code Review tasks?
– iBug
Nov 10 at 13:50
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
Nov 10 at 14:07
add a comment |
up vote
4
down vote
up vote
4
down vote
The immediate issue in your code is the syntax error on the line reading
if [` $x -eq 0 `]
The [
and ]
must be separated from the arguments within by a space character. Also, the command substitution on this line, `$x -eq 0`
, is nonsensical as it would try to run the value of $x
as a command.
You also have issues with non-quoting of your variable expansions, which disqualifies your script from working on filenames containing whitespace characters and filename globbing patterns.
The script also unconditionally clobbers the file newfile
needlessly (and would fail if newfile
was the name of an existing directory) and it lacks a #!
-line.
There is no point in asking the user interactively for file paths. It would be better for the user to be able to make use of the shell's filename completion on the command line and provide the pathnames to the files there as two operands:
$ ./script.sh some/path/file1 some/other/path/file2
If running the script in this way, the two pathnames will be available inside the script as "$1"
and "$2"
.
The cmp
utility can be used in this script without creating a temporary file. Instead of redirecting its output, make it quiet by using its -s
option (for "silent") and use its exit status to determine if the two files were identical or not.
The script would look like
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
Or, shorter,
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
This would call rm -i
on the second of the two given pathnames if it referred to a file with identical contents as the first pathname. The --
in the cmp
and rm
commands is necessary to avoid interpreting a filename starting with a dash as a set of options.
The issue with this script, as with your own script, is that if you give it the same pathname twice, i.e. you compare a file against itself, then it will offer to remove it.
Therefore, we also need to make sure that the two pathnames refer to two different files.
You can do that by comparing the two pathname strings with each other:
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
This may be enough for most applications but does not take symbolic links into account. In some shells you can also use the non-standard -ef
test ("equal file") which tests whether two pathnames refer to the same file (same i-node number and device):
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
or,
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
And with some sanity checks (also moving the -ef
test to the sanity checks section):
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:nt%s file1 file2n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same filen' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
Note that quoting the variable expansions is important since it's not uncommon for pathnames to contain spaces (on macOS, this is very common). Double quoting variable expansions also stops them from being interpreted as shell globbing patterns (your code would, for example, not work on a file called *
). Also note the use of a #!
-line appropriate for the script.
If your homework assignment requires you to read the pathnames of the two files interactively, then do that with read -r
and with IFS
set to an empty string. This would allow you to read pathnames starting with whitespace characters and containing characters:
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same filen' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
Related:
- Why does my shell script choke on whitespace or other special characters?
- Understanding "IFS= read -r line"
- ShellCheck.net
If you at some point need to check whether a file is empty, as in your own code, then don't call wc
on it (it is inefficient as it would have to read the whole file). Instead, use a -s
test:
if [ -s "$pathname" ]; then
printf '%s has non-zero sizen' "$pathname"
else
printf '%s is empty (or does not exist)n' "$pathname"
fi
See man test
on your system, or refer to the POSIX standard for this utility.
The immediate issue in your code is the syntax error on the line reading
if [` $x -eq 0 `]
The [
and ]
must be separated from the arguments within by a space character. Also, the command substitution on this line, `$x -eq 0`
, is nonsensical as it would try to run the value of $x
as a command.
You also have issues with non-quoting of your variable expansions, which disqualifies your script from working on filenames containing whitespace characters and filename globbing patterns.
The script also unconditionally clobbers the file newfile
needlessly (and would fail if newfile
was the name of an existing directory) and it lacks a #!
-line.
There is no point in asking the user interactively for file paths. It would be better for the user to be able to make use of the shell's filename completion on the command line and provide the pathnames to the files there as two operands:
$ ./script.sh some/path/file1 some/other/path/file2
If running the script in this way, the two pathnames will be available inside the script as "$1"
and "$2"
.
The cmp
utility can be used in this script without creating a temporary file. Instead of redirecting its output, make it quiet by using its -s
option (for "silent") and use its exit status to determine if the two files were identical or not.
The script would look like
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
Or, shorter,
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
This would call rm -i
on the second of the two given pathnames if it referred to a file with identical contents as the first pathname. The --
in the cmp
and rm
commands is necessary to avoid interpreting a filename starting with a dash as a set of options.
The issue with this script, as with your own script, is that if you give it the same pathname twice, i.e. you compare a file against itself, then it will offer to remove it.
Therefore, we also need to make sure that the two pathnames refer to two different files.
You can do that by comparing the two pathname strings with each other:
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
This may be enough for most applications but does not take symbolic links into account. In some shells you can also use the non-standard -ef
test ("equal file") which tests whether two pathnames refer to the same file (same i-node number and device):
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
or,
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
And with some sanity checks (also moving the -ef
test to the sanity checks section):
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:nt%s file1 file2n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same filen' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
Note that quoting the variable expansions is important since it's not uncommon for pathnames to contain spaces (on macOS, this is very common). Double quoting variable expansions also stops them from being interpreted as shell globbing patterns (your code would, for example, not work on a file called *
). Also note the use of a #!
-line appropriate for the script.
If your homework assignment requires you to read the pathnames of the two files interactively, then do that with read -r
and with IFS
set to an empty string. This would allow you to read pathnames starting with whitespace characters and containing characters:
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same filen' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
Related:
- Why does my shell script choke on whitespace or other special characters?
- Understanding "IFS= read -r line"
- ShellCheck.net
If you at some point need to check whether a file is empty, as in your own code, then don't call wc
on it (it is inefficient as it would have to read the whole file). Instead, use a -s
test:
if [ -s "$pathname" ]; then
printf '%s has non-zero sizen' "$pathname"
else
printf '%s is empty (or does not exist)n' "$pathname"
fi
See man test
on your system, or refer to the POSIX standard for this utility.
edited Nov 10 at 14:09
answered Nov 10 at 11:49
Kusalananda
115k15218351
115k15218351
did U&L recently started offering Code Review tasks?
– iBug
Nov 10 at 13:50
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
Nov 10 at 14:07
add a comment |
did U&L recently started offering Code Review tasks?
– iBug
Nov 10 at 13:50
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
Nov 10 at 14:07
did U&L recently started offering Code Review tasks?
– iBug
Nov 10 at 13:50
did U&L recently started offering Code Review tasks?
– iBug
Nov 10 at 13:50
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
Nov 10 at 14:07
@iBug Not really. To be able to help someone with coding issues, one would need to see the code. Then, it's a matter of picking it apart and suggesting better alternatives. I don't see any other way to do it. If you call it code review, then maybe it is a code review. I'm calling it answering a question.
– Kusalananda
Nov 10 at 14:07
add a comment |
up vote
3
down vote
First include shebang #!
at the top like #!/bin/bash
You are having two errors:
Instead of
cmp $file1 $file2 > newfile,
it should be
cmp -- "$file1" "$file2" > newfile
as these values of these variables may have spaces, tabs, newline (characters of $IFS
), *
, [
, ?
(wildcard characters) in them or may start with -
.
Second error:
Instead of
if [` $x -eq 0 `]
it should be
if [ "$x" -eq 0 ].
Otherwise you will get error
bash: 0: command not found.
Also if you are having whitespace or wildcards in the file names then it should be:
rm -i -- "$file2"
otherwise it can delete multiple files.
add a comment |
up vote
3
down vote
First include shebang #!
at the top like #!/bin/bash
You are having two errors:
Instead of
cmp $file1 $file2 > newfile,
it should be
cmp -- "$file1" "$file2" > newfile
as these values of these variables may have spaces, tabs, newline (characters of $IFS
), *
, [
, ?
(wildcard characters) in them or may start with -
.
Second error:
Instead of
if [` $x -eq 0 `]
it should be
if [ "$x" -eq 0 ].
Otherwise you will get error
bash: 0: command not found.
Also if you are having whitespace or wildcards in the file names then it should be:
rm -i -- "$file2"
otherwise it can delete multiple files.
add a comment |
up vote
3
down vote
up vote
3
down vote
First include shebang #!
at the top like #!/bin/bash
You are having two errors:
Instead of
cmp $file1 $file2 > newfile,
it should be
cmp -- "$file1" "$file2" > newfile
as these values of these variables may have spaces, tabs, newline (characters of $IFS
), *
, [
, ?
(wildcard characters) in them or may start with -
.
Second error:
Instead of
if [` $x -eq 0 `]
it should be
if [ "$x" -eq 0 ].
Otherwise you will get error
bash: 0: command not found.
Also if you are having whitespace or wildcards in the file names then it should be:
rm -i -- "$file2"
otherwise it can delete multiple files.
First include shebang #!
at the top like #!/bin/bash
You are having two errors:
Instead of
cmp $file1 $file2 > newfile,
it should be
cmp -- "$file1" "$file2" > newfile
as these values of these variables may have spaces, tabs, newline (characters of $IFS
), *
, [
, ?
(wildcard characters) in them or may start with -
.
Second error:
Instead of
if [` $x -eq 0 `]
it should be
if [ "$x" -eq 0 ].
Otherwise you will get error
bash: 0: command not found.
Also if you are having whitespace or wildcards in the file names then it should be:
rm -i -- "$file2"
otherwise it can delete multiple files.
edited Nov 10 at 8:19
Stéphane Chazelas
293k54547888
293k54547888
answered Nov 10 at 7:40
Debian_yadav
1,1633922
1,1633922
add a comment |
add a comment |
up vote
0
down vote
There are many ways to solve this, but I'll go with what you've started.
First, don't forget the lead off the script with the interpreter string ("shebang"):
#!/bin/bash
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
At this point you could test a couple of things:
- if newfile is not empty the files differ
if [ ! -s newfile ]; then
rm -i $file2
fi
- Test the exit code for cmp operation. If it is 0, the files match.
if [ `echo $?` == 0 ]; then
rm -i $file2
fi
Also, your wc command isn't quite working. Try running it outside of the script. Do you get the result you're expecting?
I thinkwc
command is working, when I tested it, the problem is incmp $file1 $file2 > newfile
command.
– Debian_yadav
Nov 10 at 7:48
1
Why not test withif cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...
– Kusalananda
Nov 10 at 9:49
add a comment |
up vote
0
down vote
There are many ways to solve this, but I'll go with what you've started.
First, don't forget the lead off the script with the interpreter string ("shebang"):
#!/bin/bash
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
At this point you could test a couple of things:
- if newfile is not empty the files differ
if [ ! -s newfile ]; then
rm -i $file2
fi
- Test the exit code for cmp operation. If it is 0, the files match.
if [ `echo $?` == 0 ]; then
rm -i $file2
fi
Also, your wc command isn't quite working. Try running it outside of the script. Do you get the result you're expecting?
I thinkwc
command is working, when I tested it, the problem is incmp $file1 $file2 > newfile
command.
– Debian_yadav
Nov 10 at 7:48
1
Why not test withif cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...
– Kusalananda
Nov 10 at 9:49
add a comment |
up vote
0
down vote
up vote
0
down vote
There are many ways to solve this, but I'll go with what you've started.
First, don't forget the lead off the script with the interpreter string ("shebang"):
#!/bin/bash
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
At this point you could test a couple of things:
- if newfile is not empty the files differ
if [ ! -s newfile ]; then
rm -i $file2
fi
- Test the exit code for cmp operation. If it is 0, the files match.
if [ `echo $?` == 0 ]; then
rm -i $file2
fi
Also, your wc command isn't quite working. Try running it outside of the script. Do you get the result you're expecting?
There are many ways to solve this, but I'll go with what you've started.
First, don't forget the lead off the script with the interpreter string ("shebang"):
#!/bin/bash
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
At this point you could test a couple of things:
- if newfile is not empty the files differ
if [ ! -s newfile ]; then
rm -i $file2
fi
- Test the exit code for cmp operation. If it is 0, the files match.
if [ `echo $?` == 0 ]; then
rm -i $file2
fi
Also, your wc command isn't quite working. Try running it outside of the script. Do you get the result you're expecting?
answered Nov 10 at 7:32
kevlinux
1642
1642
I thinkwc
command is working, when I tested it, the problem is incmp $file1 $file2 > newfile
command.
– Debian_yadav
Nov 10 at 7:48
1
Why not test withif cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...
– Kusalananda
Nov 10 at 9:49
add a comment |
I thinkwc
command is working, when I tested it, the problem is incmp $file1 $file2 > newfile
command.
– Debian_yadav
Nov 10 at 7:48
1
Why not test withif cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...
– Kusalananda
Nov 10 at 9:49
I think
wc
command is working, when I tested it, the problem is in cmp $file1 $file2 > newfile
command.– Debian_yadav
Nov 10 at 7:48
I think
wc
command is working, when I tested it, the problem is in cmp $file1 $file2 > newfile
command.– Debian_yadav
Nov 10 at 7:48
1
1
Why not test with
if cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...– Kusalananda
Nov 10 at 9:49
Why not test with
if cmp -s -- "$file1" "$file2"; then
? No point in the temporary file really...– Kusalananda
Nov 10 at 9:49
add a comment |
Hariom kushwaha is a new contributor. Be nice, and check out our Code of Conduct.
Hariom kushwaha is a new contributor. Be nice, and check out our Code of Conduct.
Hariom kushwaha is a new contributor. Be nice, and check out our Code of Conduct.
Hariom kushwaha is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f480903%2fhow-to-compare-two-files-and-if-found-equal-ask-the-user-to-delete-duplicate-fil%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown